欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python儿童学游戏编程知识点总结

程序员文章站 2023-11-24 14:21:52
python爬虫基本告一段落,琢磨搞点其他的,正好在网上看到一个帖子,一个外国13岁小朋友用python写的下棋程序,内容详细,也有意思,拿来练手。 13岁啊。。 我这年...

python爬虫基本告一段落,琢磨搞点其他的,正好在网上看到一个帖子,一个外国13岁小朋友用python写的下棋程序,内容详细,也有意思,拿来练手。

13岁啊。。 我这年纪还在敲 dir啥的吧

想到原先玩跑跑卡丁车时看到欧酷有个4岁熊孩子玩的完美漂移录像,深受打击,从此退出车坛。。。

废话不多说,记录一下这几天的游戏编程折腾史

游戏规则:6*6的方格棋盘,两个人轮流点击棋盘画横线或竖线,谁成功围成一个格子,这个格子算作此人的积分。

游戏架构:客户端和服务端。

先来看下游戏准备工作,需要用到pygame这个python包。

下载小朋友准备的resource文件,游戏用到的图片、声音啥的。

一下为boxgame(客户端)和server代码,已添加注释。

boxes.py

1 import pygame

import math
from podsixnet.connection import connectionlistener,connection
from time import sleep

# 客户端游戏类
class boxesgame(connectionlistener):
  def initsound(self):
    pygame.mixer.music.load("music.wav")
    self.winsound=pygame.mixer.sound('win.wav')
    self.losesound=pygame.mixer.sound('lose.wav')
    self.placesound=pygame.mixer.sound('place.wav')
    pygame.mixer.music.play()
  # 收到来自server的 action:close指令后调用下面方法
  def network_close(self,data):
    exit()
  def network_yourturn(self,data):
    self.turn=data['torf']
  def network_startgame(self,data):
    self.running=true
    self.num=data["player"]
    self.gameid=data["gameid"]
  def network_place(self,data):
    self.placesound.play()
    x=data["x"]
    y=data["y"]
    hv=data["is_horizontal"]
    if hv:
      self.boardh[y][x]=true
    else:
      self.boardv[y][x]=true
  # 设定某个格子为自己的
  def network_win(self,data):
    self.owner[data["x"]][data["y"]]="win"
    self.boardh[data["y"]][data["x"]]=true
    self.boardv[data["y"]][data["x"]]=true
    self.boardh[data["y"]+1][data["x"]]=true
    self.boardv[data["y"]][data["x"]+1]=true
    self.winsound.play()
    self.me+=1
  def network_lose(self,data):
    self.owner[data["x"]][data["y"]]="lose"
    self.boardh[data["y"]][data["x"]]=true
    self.boardv[data["y"]][data["x"]]=true
    self.boardh[data["y"]+1][data["x"]]=true
    self.boardv[data["y"]][data["x"]+1]=true
    self.losesound.play()
    self.otherplayer+=1

  def __init__(self):
    self.justplaced=10
    pygame.init()
    pygame.font.init()
    width, height = 389, 489
    self.me = 0
    self.otherplayer = 0
    self.didwin = false
    self.gameid=none
    self.num=none
    self.num=0
    self.screen = pygame.display.set_mode((width, height))
    self.owner=[[0 for x in range(6)] for y in range(6)]
    self.clock = pygame.time.clock()
    self.turn = true
    self.running=false
    self.boardh = [[false for x in range(6)] for y in range(7)]
    self.boardv = [[false for x in range(7)] for y in range(6)]
    print(self.boardh)
    print(self.boardv)
    self.initgraphics()
    self.initsound()
    self.drawhud()
    pygame.display.set_caption("boxes")

    # address=raw_input("host:port(localhost:8080):")
    # try:
    #   if not address:
    #     host,port="localhost",3721
    #   else:
    #     host,port=address.split(":")
    #   self.connect((host,port))
    # except:
    #   print("error connecting to server")
    #   print("usage: host:port")
    #   print("eg 127.0.0.1;3721")
    #   exit()
    self.connect()
    print("boxes client started")
    while not self.running:
      self.pump()
      connection.pump()
      self.running=true
      sleep(0.01)
      print("not running ,connecting...")
    if self.num==0:
      # self.turn=true
      self.marker=self.greenplayer
      self.othermarker=self.blueplayer
    else:
      self.turn=false
      self.marker=self.blueplayer
      self.othermarker=self.greenplayer


  def initgraphics(self):
    self.normallinev = pygame.image.load("normalline.png")
    self.normallineh = pygame.transform.rotate(self.normallinev, -90)
    self.bar_donev = pygame.image.load("bar_done.png")
    self.bar_doneh = pygame.transform.rotate(self.bar_donev, -90)
    self.hoverlinev = pygame.image.load("hoverline.png")
    self.hoverlineh = pygame.transform.rotate(self.hoverlinev, -90)
    # self.boardh[5][4]=true
    # self.boardv[5][5]=true
    self.separators = pygame.image.load("separators.png")
    self.score_panel = pygame.image.load("score_panel.png")
    self.redindicator = pygame.image.load("redindicator.png")
    self.greenindicator = pygame.image.load("greenindicator.png")
    self.greenplayer = pygame.image.load("greenplayer.png")
    self.blueplayer = pygame.image.load("blueplayer.png")
    self.winningscreen = pygame.image.load("youwin.png")
    self.gameover = pygame.image.load("gameover.png")

  def drawboard(self):
    for x in range(6):
      for y in range(7):
        if not self.boardh[y][x]:
          self.screen.blit(self.normallineh, [(x) * 64 + 5, (y) * 64])
        else:
          self.screen.blit(self.bar_doneh, [(x) * 64 + 5, (y) * 64])
    for x in range(7):
      for y in range(6):
        if not self.boardv[y][x]:
          self.screen.blit(self.normallinev, [(x) * 64, (y) * 64 + 5])
        else:
          self.screen.blit(self.bar_donev, [(x) * 64, (y) * 64 + 5])

  def update(self):
    # 判断方格是否已经都有归属
    if self.me+self.otherplayer==36:
      self.didwin=true if self.me>self.otherplayer else false
      return 1
    self.justplaced-=1
    # print('pump connect info')
    connection.pump()
    self.pump()
    # print('pump connect info finish')
    self.clock.tick(60)
    self.screen.fill(0)
    self.drawboard()
    self.drawhud()
    self.drawownermap()
    for event in pygame.event.get():
      if event.type == pygame.quit:
        exit()

    mouse = pygame.mouse.get_pos()
    xpos = int(math.ceil((mouse[0] - 32) / 64.0))
    ypos = int(math.ceil((mouse[1] - 32) / 64.0))
    # 判断鼠标位置更接近与那条线
    is_horizontal = abs(mouse[1] - ypos * 64) < abs(mouse[0] - xpos * 64)
    ypos = ypos - 1 if mouse[1] - ypos * 64 < 0 and not is_horizontal else ypos
    xpos = xpos - 1 if mouse[0] - ypos * 64 < 0 and is_horizontal else xpos

    board = self.boardh if is_horizontal else self.boardv
    isoutofbounds = false

    try:
      if not board[ypos][xpos]: self.screen.blit(self.hoverlineh if is_horizontal else self.hoverlinev,
                            [xpos * 64 + 5 if is_horizontal else xpos * 64,
                            ypos * 64 if is_horizontal else ypos * 64 + 5])
    except:
      isoutofbounds = true
      pass
    if not isoutofbounds:
      alreadyplaced = board[ypos][xpos]
    else:
      alreadyplaced = false
    # 鼠标点击时,发送place信号给自己划线
    if pygame.mouse.get_pressed()[0] and not alreadyplaced and not isoutofbounds and self.turn==true and self.justplaced<=10:
      self.justplaced=10
      if is_horizontal:
        self.boardh[ypos][xpos] = true
        self.send({"action":"place","x":xpos,"y":ypos,"is_horizontal":is_horizontal,"gameid":self.gameid,"num":self.num})
      else:
        self.boardv[ypos][xpos] = true
        self.send({"action":"place","x":xpos,"y":ypos,"is_horizontal":is_horizontal,"gameid":self.gameid,"num":self.num})
    pygame.display.flip()
  # 画记分区域
  def drawhud(self):
    self.screen.blit(self.score_panel, [0, 389])
    myfont = pygame.font.sysfont(none, 32)
    label = myfont.render("your turn", 1, (255, 255, 255))
    self.screen.blit(label, (10, 400))
    self.screen.blit(self.greenindicator if self.turn else self.redindicator ,(130, 395))
    myfont64 = pygame.font.sysfont(none, 64)
    myfont20 = pygame.font.sysfont(none, 20)

    scoreme = myfont64.render(str(self.me), 1, (255, 255, 255))
    scoreother = myfont64.render(str(self.otherplayer), 1, (255, 255, 255))
    scoretextme = myfont20.render("you", 1, (255, 255, 255))
    scoretextother = myfont20.render("other player", 1, (255, 255, 255))

    self.screen.blit(scoretextme, (10, 425))
    self.screen.blit(scoreme, (10, 435))
    self.screen.blit(scoretextother, (280, 425))
    self.screen.blit(scoreother, (280, 435))
  # 给占领与被占领格子着色
  def drawownermap(self):     
    for x in range(6):
      for y in range(6):
        if self.owner[x][y]!=0:
          if self.owner[x][y]=="win":
            self.screen.blit(self.marker,(x*64+5,y*64+5))
          if self.owner[x][y]=="lose":
            self.screen.blit(self.othermarker,(x*64+5,y*64+5))
  # 游戏结束后显示gameover或winning的图案
  def finished(self):
    self.screen.blit(self.gameover if not self.didwin else self.winningscreen,(0,0))
    while 1:
      for event in pygame.event.get():
        if event.type==pygame.quit:
          exit()
      pygame.display.flip()


bg = boxesgame()
while 1:
  if bg.update()==1:
    break
bg.finished()

server.py

1 __author__ = 'administrator'

import podsixnet.channel
import podsixnet.server
from time import sleep

# 定义客户端通道,继承podsixnet.channel.channel
class clientchannel(podsixnet.channel.channel):
  def network(self,data):
    print data
  def network_place(self,data):
    hv=data["is_horizontal"]
    x=data["x"]
    y=data["y"]
    # 客户标号
    num=data["num"]
    # 本游戏id
    self.gameid=data["gameid"]
    self._server.placeline(hv,x,y,data,self.gameid,num)
  def close(self):
    self._server.close(self.gameid)

# 定义游戏服务端
class boxesserver (podsixnet.server.server):
  channelclass = clientchannel
  def __init__(self,*args,**kwargs):
    podsixnet.server.server.__init__(self,*args,**kwargs)
    self.games=[]
    self.queue=none
    self.currentindex=0
  def connected(self,channel,addr):
    print 'new connection:',channel
    # 如果队列为空,则新建一局game
    if self.queue==none:
      self.currentindex+=1
      channel.gameid=self.currentindex
      self.queue=game(channel,self.currentindex)
    #如果队列中已有一局game在等待,则将新连进来的channel作为第二名游戏者与等待游戏者配对,加入games[]列表,将queue清空
    else:
      channel.gameid=self.currentindex
      self.queue.player1=channel
      self.queue.player0.send({"action":"startgame","player":0,"gameid":self.queue.gameid})
      self.queue.player1.send({"action":"startgame","player":1,"gameid":self.queue.gameid})
      self.games.append(self.queue)
      self.queue=none
  # def placeline(self,is_h,x,y,data,gameid,num):
  #   if num==self.turn:
  #     self.turn=0 if self.turn else 1
  #     self.player1.send({"action":"yourturn","torf":true if self.turn==1 else false})
  #     self.player0.send({"action":"yourturn","torf":true if self.turn==0 else false})
  #     if is_h:
  #       self.boardh[y][x]=true
  #     else:
  #       self.boardv[y][x]=true
  #     self.player0.send(data)
  #     self.player1.send(data)

  #通知gameserver哪句游戏要划线,调用游戏placeline
  def placeline(self,is_h,x,y,data,gameid,num):
    game=[a for a in self.games if gameid==a.gameid]
    if len(game)==1:
      game[0].placeline(is_h,x,y,data,num)
  # 关闭某局game
  def close(self,gameid):
    try:
      game=[a for a in self.games if a.gameid==gameid][0]
      game.player0.send({"action":"close"})
      game.player1.send({"action":"close"})
    except:
      pass
  # 判断方格归属
  def tick(self):
    index=0
    # 状态未改变 code 3
    change=3
    # 扫描每局游戏
    for game in self.games:
      change=3
      # 扫描2次,因为存在放置一个线条完成两个方格占领的情况
      for time in range(2):
        for y in range(6):
          for x in range(6):
            # 判断是否是新围成的方格
            if game.boardh[y][x] and game.boardv[y][x] and game.boardh[y+1][x] and game.boardv[y][x+1] and not game.owner[x][y]:
              # 是否为己方围成的,围成的一方可以继续走一步
              # 此处self.games[index]能否替换为game?
              if self.games[index].turn==0:
                self.games[index].owner[x][y]=2
                game.player1.send({"action":"win","x":x,"y":y})
                game.player0.send({"action":"lose","x":x,"y":y})
                change=1
                print("player1 win 1 grid")
              else:
                self.games[index].owner[x][y]=1
                game.player0.send({"action":"win","x":x,"y":y})
                game.player1.send({"action":"lose","x":x,"y":y})
                change=0
                print("player0 win 1 grid")
      # 如果状态改变了(即有一方完成了方格占领)则下一步仍由该方走棋;否则正常交替走棋
      self.games[index].turn=change if change!=3 else self.games[index].turn
      game.player1.send({"action":"yourturn","torf":true if self.games[index].turn==1 else false})
      game.player0.send({"action":"yourturn","torf":true if self.games[index].turn==0 else false})
      index+=1
    self.pump()

# 单纯一局游戏的控制类
class game:
  def __init__(self,player0,currentindex):
    self.turn=0
    self.owner=[[false for x in range(6)] for y in range(6)]
    self.boardh=[[false for x in range(6)] for y in range(7)]
    self.boardv=[[false for x in range(7)] for y in range(6)]
    self.player0=player0
    self.player1=none
    self.gameid=currentindex


    # while not self.running:
    #   self.pump()
    #   connection.pump()
    #   sleep(0.01)
    # if self.num==0:
    #   self.turn=true
    #   self.marker=self.greenplayer
    #   self.othermarker=self.blueplayer
    # else:
    #   self.turn=false
    #   self.marker=self.blueplayer
    #   self.othermarker=self.greenplayer
  # 划线
  def placeline(self,is_h,x,y,data,num):
    if num==self.turn:
      self.turn=0 if self.turn else 1
      self.player1.send({"action":"yourturn","torf":true if self.turn==1 else false})
      self.player0.send({"action":"yourturn","torf":true if self.turn==0 else false})
      if is_h:
        self.boardh[y][x]=true
      else:
        self.boardv[y][x]=true
      self.player0.send(data)
      self.player1.send(data)
  # def network_palce(self,data):
  #   x=data["x"]
  #   y=data["y"]
  #   hv=data["is_horizontal"]
  #   if hv:
  #     self.boardh[y][x]=true
  #   else:
  #     self.boardv[y][x]=true


print "staring server on localhost"
address=raw_input("host:port(localhost:8080):")
if not address:
  host,port="localhost",31425
  print("default host and port")
  print(host,":",port)
else:
  host,port=address.split(":")
  print(host,":",port)

boxesserver=boxesserver( localaddr=("127.0.0.1", 31425))
# boxesserver=boxesserver()
while true:
  boxesserver.pump()
  boxesserver.tick()
  sleep(0.01) 就是这样,休息,休息一下。

以上就是本次介绍的儿童学习python游戏编程的全部知识点内容,感谢大家对的支持。