Python菜鸟快乐游戏编程_pygame(6)

Python菜鸟快乐游戏编程_pygame(博主录制,2K分辨率,超高清)

https://study.163.com/course/courseMain.htm?courseId=1006188025&share=2&shareId=400000000398149

 

上周,有个朋友对我说,Toby,你弄游戏编程这玩意没啥实用性,应该录制更多Python机器学习和人工智能的视频。我对那位朋友说,游戏就是人工智能最好的训练场所。不管扫雷,奥赛罗棋,围棋,象棋,跳棋,星际争霸都是基于算法的,通过人工智能AI,我们可以获取更高胜率。同时我告诫各位年轻朋友,游戏是会上瘾的。一个商业游戏如果不能让玩家上瘾,那就是一款失败游戏。因此我们会看到无数年轻人在网吧沉醉不知归路。我也有过类似经历,上瘾后,如果不能继续玩下去,全身都难受,继续玩下去,全身软绵绵想吐。

游戏就是别人设计的程序。与其活在别人程序里,不如开发自己游戏,还能学习编程和算法,获取一年几十万高薪。

此节课以扫雷为例,讲解神经网络算法生成模型,通过模型来自动扫雷,这就是简单人工智能。

感谢作者Nolan Baker对pygame社区贡献,为大家奉献这款游戏,作者邮箱是:

 <hendersonhasselbalch@gmail.com>

朋友们可以训练数据,尝试更多算法,最终搞一个算法夺旗比赛,看看谁的算法胜率更高。

首先打开smartsweeper文件夹,进入子文件夹smartsweeper beta,所有脚本都放在这里

neural_network.py 这脚本主要是通过神经网络算法,生成一个模型。
# -*- coding: utf-8 -*-
"""
Created on Sun Oct  7 10:16:24 2018
作者邮件:231469242@qq.com
作者微信公众号:PythonEducation
"""

#
#       neural_network.py
#
#       Copyright 2010 Nolan Baker <hendersonhasselbalch@gmail.com>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import random, os, math
from numpy import *
import numpy.random as nrand

################################################################################
# Useful Vector Functions
################################################################################
def sigmoid(x):
    return 1.0 / (1 + math.exp(-x))
sigmoid = vectorize(sigmoid, otypes=[float])

def sigPrime(x):
    # in terms of the output of the sigmoid function
    # otherwise would be sig(x) - sig^2(x)
    return x - x ** 2
sigPrime = vectorize(sigPrime, otypes=[float])

def oneMinus(x):
    return 1 - x
oneMinus = vectorize(oneMinus, otypes=[float])

def sub(x,y):
    return x - y
sub = vectorize(sub, otypes=[float])

################################################################################
# Neural Network
################################################################################
class NeuralNet:
    def __init__(self, i, h, o):
        self.w_ih = mat(nrand.uniform(-.05, .05,(i,h)))
        self.w_ho = mat(nrand.uniform(-.05, .05,(h,o)))
        self.m_ih = mat(zeros((i,h)))
        self.m_ho = mat(zeros((h,o)))

    def getOut(self, i):
        self.h = sigmoid(mat(i) * self.w_ih)
        return sigmoid(self.h * self.w_ho).tolist()[0]

    def train(self, i, t, a = .1, b = .01):

        # get output of our neural network
        out = mat(self.getOut(i))

        # calc deltas
        d_o = mat(asarray(out) * asarray(oneMinus(out)) *
                  asarray(sub(mat(t), out)))
        d_h = mat(asarray(self.h) * asarray(oneMinus(self.h)) *
                  asarray(d_o * self.w_ho.T))

        # update weights
        c_ih = mat(i).T * d_h
        self.w_ih = add(add(self.w_ih, a * c_ih), b * self.m_ih)
        self.m_ih = c_ih
        c_ho = self.h.T * d_o
        self.w_ho = add(add(self.w_ho, a * c_ho), b * self.m_ho)
        self.m_ho = c_ho

################################################################################
# example
################################################################################
def main():

    nn = NeuralNet(2,10,1)
    examples = [([0,1], [1]),
                ([1,1], [0]),
                ([1,0], [1]),
                ([0,0], [0])]

    for i in range(10000):
        print i
        x = random.randint(0,4)
        nn.train(examples[x][0], examples[x][1], 3)

    print nn.getOut([0,1])
    print nn.getOut([1,1])
    print nn.getOut([1,0])
    print nn.getOut([0,0])

if __name__ == '__main__':
    main()


agent.py生成一个机器人,代理玩家自动扫雷
# -*- coding: utf-8 -*-
"""
Created on Sun Oct  7 10:16:24 2018
作者邮件:231469242@qq.com
作者微信公众号:PythonEducation
"""
#
#       agent.py
#
#       Copyright 2010 Nolan Baker <hendersonhasselbalch@gmail.com>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import random, pygame, os
from pygame.locals import *
from game import *
from state import *
from neural_network import *

# FLOATING POINT NUMBERS BETWEEN 0 and 1
THRESH = .18
INITIAL = 1
ALPHA = .05
BETA = .01
OPEN_MIND = 1 
HUG_EDGE = 1
BRN2GRN = 0
GREED = 0
EXPLORE = .7
NUM_POS = 5
THRESH = .16
INITIAL = 1
TO_DIG = 1 # low numbers make digging difficult
TO_FLAG = 1 # low numbers make flagging difficult
TO_UNFLAG = 1 # low numbers make unflagging easy
WEIGHT = .005
ALLOW_REPEATS = 0 #percentage of repeats allowed

# FLOATS LARGER THAN 1
SPEED_AMT = 1.00191 # increased threshold change
CHANGE = 1.000173 # normal threshold change

# INTEGERS
NUM_POS = 8
MAX_MOVES = 42000
MOVES_LEARNED = 4000
SPEED_MOVES = 15000
INPUT_GRID = 5
OUTPUT_GRID = 3

# BOOLEAN
SHARE_MAP = True
RESET_MOVES = False # do you want your move list to empty after each game?
CHEAT = False

################################################################################
# Intelligent Agent
################################################################################

class Agent:
    def __init__(self, game):
        self.game = game
        self.human = 0
        self.clearMoves()
        self.name2num_dict = {}
        names = "012345678f_"
        self.in_size = len(names)
        for i in range(len(names)):
            nodes = ([0] * 11)
            nodes[i] = 1
            self.name2num_dict[names[i]] = nodes
        a = (INPUT_GRID**2)*(11)
        b = OUTPUT_GRID**2
        self.nn = NeuralNet(a,a,b)
        self.cheat = CHEAT
        self.memory = []
        self.alpha = ALPHA
        self.beta = BETA
        self.move_list = []
    def switch(self):
        self.human = 1 - self.human
            
    def clearMoves(self):
        self.num_moves = 0
        self.closed = []
        self.thresh = INITIAL #* random.random()
        if self.human and self.game.draw_board:
            x, y = pygame.mouse.get_pos()
            if self.game.torus:
                x %= self.game.width
                y %= self.game.height
            else:
                if x >= self.game. x = self.game.width - 1 
                elif x < 0: x = 0
                if y >= self.game.height: y = self.game.height - 1 
                elif y < 0: y = 0
            s = (x, y)
            
        else: 
            #s = (random.randint(0, self.game.width),
            #     random.randint(0, self.game.height))
            s = (0,0)
        self.old_pos = s
        self.pos = s
        self.old_action = "L"
        self.action = "L"
        if RESET_MOVES:
            self.move_list = []
        if not SHARE_MAP: self.guess = {}
        self.visited = {}
        self.certainty = {}
        for i in range(self.game.width):
            for j in range(self.game.height):
                if not SHARE_MAP: self.guess[(i,j)] = .5
                self.visited[(i,j)] = 0
                self.certainty[(i,j)] = .5

    def mouse2Grid(self, pos):
        x, y = pos
        x = int(x / self.game.tile_size)
        y = int(y / self.game.tile_size)
        return (x, y)

    def getArea(self,x,y,n):
        area = []
        for j in range(n):
            b = y + j - int(n / 2)
            for i in range(n):
                a = x + i - int(n / 2)
                if self.game.torus:
                    a %= self.game.width
                    b %= self.game.height
                area.append((a, b))
        return area

    def boardArea(self):
        area = []
        for j in range(self.game.height):
            for i in range(self.game.width):
                area.append((i,j))
        return area

    def threshClick(self):
        x,y = self.pos
        # get the guess for the space you're on
        if SHARE_MAP:
            out = self.game.guess[self.pos]
        else: out = self.guess[self.pos]
        
        
        
        name = self.game.board[self.pos]
        m = self.num_moves
        speed = 1
        if m == SPEED_MOVES:
            print "speeding up"
        if m > SPEED_MOVES:
            speed = SPEED_AMT
        self.thresh *= CHANGE * speed
        if m == MAX_MOVES:
            print "giving up"
        if m < MAX_MOVES:
            if out <= self.thresh * TO_DIG and name != "f":
                #print "dig"
                self.close(self.pos)
                cleared = self.game.dig(self.pos) # how many spaces we cleared
                #self.visited[(x,y)] += 5
                #if name not in "012345678" and m > SPEED_MOVES:
                if cleared != 0:
                    self.thresh = THRESH * speed
            elif (out * TO_UNFLAG <= self.thresh and name == "f"):
                #print "unflag"
                self.open(self.pos)
                self.game.mark(self.pos)
                #self.thresh = THRESH * speed
                #self.wholeBoard()
            elif (out * TO_FLAG >= (1 - self.thresh) and name != "f"):
                #print "flag"
                self.close(self.pos)
                self.game.mark(self.pos)
                #self.visited[self.pos] += 5
                self.thresh = THRESH * speed
                #self.wholeBoard()

        # if you've gone so many moves without ending the game, do it
        elif name == "f":
            self.game.mark(self.pos)
            self.game.throwTowel()
        else:
            self.game.dig(self.pos)
            self.game.throwTowel()
        
        if name == "0":
            pass#self.visited[(x,y)] += 10

    def simMove(self):
        ############################################################
        # MOVEMENT
        ############################################################
        x,y = self.pos
        # if you're on green, move to brown (most of the time)
        area = self.getArea(x,y,3)
        von_neumann = [(x,y+1),(x,y-1),(x+1,y),(x-1,y)]
        possible = []
        if random.random() < HUG_EDGE:
            for pos in area:
                if self.pos == pos:
                    continue
                try:
                    a = self.game.board[self.pos]
                    grn = "_f"
                    brn = "012345678"
                    if (a in grn) and (self.game.board[pos] in brn):
                        possible.append(pos)
                    if (random.random < BRN2GRN and (a in brn) and
                        (self.game.board[pos] in grn) and
                        (pos in von_neumann)):
                        possible.append(pos)
                except: pass

        # if this isn't possible, anywhere is fine
        if len(possible) == 0 or random.random < EXPLORE:
            possible = area

        # find the spot you've visited least
        m = 9999999999
        s = []
        for pos in possible:
            if pos == self.pos:
                continue
            try:
                v = self.visited[pos]
                if v < m:
                    m = v
                    s = [pos]
                elif v == m:
                    s.append(pos)
            except:
                pass
        random.shuffle(s)

        # move to the best guess on the board
        if random.random() < GREED:
            random.shuffle(self.best_guesses)
            self.pos = self.best_guesses[0]
        
        # and go to it
        else:
            self.pos = s[0]
        #self.visited[self.pos] += 1

    def scanMove(self):
        x, y = self.pos
        x = (x + 1) % self.game.width
        if x == 0:
            y = (y + 1) % self.game.height
        self.pos = (x, y)
        
    def wholeBoard(self):
        p = []
        for i in range(self.game.width):
            for j in range(self.game.height):
                p.append((i,j))
        random.shuffle(p)
        for s in p:
            self.getNNOutOf(s)
            
    def getNNOutOf(self, p):
        x,y = p
        
        # figure out where your are and what's around you
        self.area = self.getArea(x,y,OUTPUT_GRID)
        self.area2 = self.getArea(x,y,INPUT_GRID)

        # GET INPUT FROM AREA AROUND YOU
        input = []
        max_in = 0
        for pos in self.area2:
            try:
                name = self.game.board[pos]
                try:
                    if int(name) > max_in:
                        max_in = int(name)
                except:
                    pass
                nodes = self.name2num_dict[name]
                input += nodes
            except:
                input += [0] * len(self.name2num_dict["0"])
        self.input = input
        self.max_in = max_in
        
        # FIGURE OUT WHAT YOUR TARGET OUTPUT SHOULD BE
        # this is not used to determine where to go or what to do
        # it is only used durring the learning phase
        target = []
        for i in range(len(self.area)):
            pos = self.area[i]
            try:
                num = self.game.mine_array[pos]
                target.append(num)
            except:
                target.append(.5)
        self.target = target

        ################################################################
        # get output from neural net
        ################################################################
        # uncomment this to play perfectly (cheat)
        # for learning examples quicker
        if self.cheat:
            print "cheating"
            output = target
        else: 
            output = self.nn.getOut(input)
        self.output = output
            
        
        certainty = sum(output)/float(len(output))
        certainty = max(certainty, 1-certainty)
        self.certainty[self.pos] = certainty
        
        weight = WEIGHT
        # update your guesses for whether or not a square has a mine
        for i in range(OUTPUT_GRID**2):
            try:
                if SHARE_MAP:
                    output[i] = self.game.guess[self.area[i]] * (1-weight) + output[i] * weight
                    self.game.guess[self.area[i]] = output[i]
                else:
                    output[i] = self.guess[self.area[i]] * (1-weight) + output[i] * weight
                    self.guess[self.area[i]] = output[i]
            except:
                pass # this just means we're looking out of bounds

    def act(self):
        if not self.game.FINISHED:
            self.old_pos = self.pos
            x,y = self.pos
            self.getNNOutOf(self.pos)
            ################################################################
            # Q STUFF
            ################################################################
            '''
            output = self.output
            out_array = []
            count = 0
            for a in range(OUTPUT_GRID):
                out_array.append([])
                for b in range(OUTPUT_GRID):
                    try:
                        if output[count] < .5: o = 0
                        elif self.game.board[self.pos] == "f": o = -1
                        else: o = 1
                        out_array[a].append(o)
                        count += 1
                    except:
                        out_array[a].append(0)
            ahha = False
            for s in self.memory:
                ahha = s.isMatch(out_array)
                if ahha:
                    state = s
                    break
            if not ahha:
                state = State(out_array)
                self.memory.append(state)

            action_i = state.getActionIndex()
            action = state.actions[action_i]
            '''
            
            ################################################################
            # EVENT LOOP - if you're drawing the board, check for events
            ################################################################
            if self.human:
                
                found = False
                if self.game.draw_board:
                    for i in range(5000):
                        event = pygame.event.poll()
                        
                        if event.type == QUIT:
                            self.game.running = False
                            pygame.quit ()
                            break

                        elif event.type == KEYDOWN:
                            if event.key == K_r:
                                self.switch()
                                break
                            if event.key == K_ESCAPE:
                                self.game.running = False
                                pygame.quit ()
                                break
                            if event.key == K_c:
                                self.cheat = bool(1 - int(self.cheat))
                                break
                            if event.key == K_g:
                                self.game.goggles = (self.game.goggles + 1) % 3
                                break


                        # if something is clicked
                        elif event.type == MOUSEBUTTONDOWN:
                            if event.button == 1:
                                cleared = self.game.dig(self.pos)
                                found = True
                                '''
                                state.reward("L")
                                state.punish("R")
                                '''
                            if event.button == 3:
                                self.game.mark(self.pos)
                                found = True
                                '''
                                state.reward("R")
                                state.punish("L")
                                '''
                                
                        elif event.type == MOUSEMOTION:
                            self.old_pos = self.pos
                            self.pos = self.mouse2Grid(event.pos)
                            x, y = self.pos
                            a, b = self.old_pos
                            if self.old_pos != self.pos:
                                '''
                                if x > a:
                                    state.reward("E")
                                    state.punish("W")
                                if x < a:
                                    state.reward("W")
                                    state.punish("E")
                                if y > a:
                                    state.reward("S")
                                    state.punish("N")
                                if y < a:
                                    state.reward("N")
                                    state.punish("S")
                                '''
                                found = True
                        
                        else:
                            self.pos = self.mouse2Grid(pygame.mouse.get_pos())



            ################################################################
            # BOT SPECIFIC STUFF
            ################################################################
            elif not self.human:
                found = False
                if self.game.draw_board:
                    for i in range(10):
                        event = pygame.event.poll()
                        if event.type == KEYDOWN:
                            if event.key == K_h:
                                self.switch()
                            if event.key == K_c:
                                self.cheat = bool(1 - int(self.cheat))
                                break
                            if event.key == K_g:
                                self.game.goggles = (self.game.goggles + 1) % 3
                                break    
                            if event.key == K_ESCAPE:
                                self.game.running = False
                                pygame.quit ()
                                break
                                
                        if event.type == QUIT:
                            self.game.running = False
                            pygame.quit ()
                            break
                            

                        found = True
                #self.wholeBoard()
                self.threshClick()
                self.getCertainty()
                self.simMove()
                '''
                x, y = self.pos

                if action == "L":
                    self.game.dig(self.pos)
                elif action == "R":
                    self.game.mark(self.pos)
                elif action == "N":
                    y -= 1
                elif action == "E":
                    x += 1
                elif action == "S":
                    y += 1
                elif action == "W":
                    x -= 1
                elif action == "J":
                    x = random.randint(0, self.game.width - 1)
                    y = random.randint(0, self.game.height - 1)

                if x < 0: x = 0
                if x > self.game. x = self.game.width
                if y < 0: y = 0
                if y > self.game.height: y = self.game.height
                self.pos = x, y
                '''
            ################################################################
            # Remember what you've done.
            ################################################################
            if found:
                m = [self.input, self.target, self.max_in]
                if (random.random() < ALLOW_REPEATS or 
                    m not in self.move_list):
                    self.move_list.append(m)
                    #print len(self.move_list)
                if len(self.move_list) > MOVES_LEARNED:
                    #r = random.randint(0, len(self.move_list))
                    #self.move_list = self.move_list[:r] + self.move_list[r+1:]
                    self.move_list = self.move_list[1:]
                self.num_moves += 1
                
            
            '''if self.num_moves == MOVES_LEARNED:
                print "truncating move list"
            if self.num_moves == MAX_MOVES / 20:
                print "5%"
            if self.num_moves == MAX_MOVES / 4:
                print "1/4"
            if self.num_moves == MAX_MOVES / 2:
                print "half way"'''
                
    def getCertainty(self):
        ############################################################
        # how certain are you that you've chosen correctly
        ############################################################
        self.best_guesses = [self.pos]
        best = self.pos
        lowest_errors = [1]
        lowest = 1
        global_certainty = 0
        local_certainty = 0
        for i in range(self.game.width):
            for j in range(self.game.height):
                if SHARE_MAP:
                    g = self.game.guess[(i,j)]
                else:
                    g = self.guess[(i,j)]
                err = min(g, 1-g) ** 2
                global_certainty += 1 - err
                if (i,j) in self.area:
                    local_certainty += 1 - err
                if (i,j) in self.closed and random.random() < .9:
                    continue
                if err < max(lowest_errors):
                    lowest_errors.append(err)
                    self.best_guesses.append((i,j))
                    if len(self.best_guesses) > NUM_POS:
                        self.best_guesses = self.best_guesses[1:]
                        lowest_errors = lowest_errors[1:]
                    if err < lowest:
                        best = (i,j)
                        lowest = err

        global_certainty /= float(self.game.width * self.game.height)
        local_certainty /= float(self.game.width * self.game.height)

    def QLearn(self, move, reward, threshold = .05, decay = .7):
        # while there's reward and states left
        while reward > threshold and move >= 0:

            # reward the state at 'move', an int
            pos = self.move_list[move][0]
            input = self.move_list[move][1]
            n = max(max(input), 0)
            target = self.move_list[move][2]

            for i in range(n):
                self.nn.train(input, target, reward)

            # then reduce your reward and move to the previous state
            move -= 1
            reward *= decay

    def open(self, pos):
        if pos in self.closed:
            self.closed.remove(pos)

    def close(self, pos):
        if pos not in self.closed:
            self.closed.append(pos)

    def learn(self):
        # go through each move and back propogate rewards
        index = 0
        #avg_num = 0
        for index in range(len(self.move_list)):
            move = self.move_list[index]
            self.nn.train(move[0], move[1],self.alpha, self.beta)
            #avg_num += move[2]
        #avg_num /= float(len(self.move_list))
        self.alpha *= OPEN_MIND
        self.beta *= OPEN_MIND
        #print avg_num
        #print self.alpha, self.beta
        
    def reward(self, i, amt):
        self.state.rewards[i] += amt

    def punish(self, i, amt):
        self.reward(i, -amt)

    def setPos(self, pos):
        self.pos = pos

    def getNumMineGuess(self):
        sum = 0
        if SHARE_MAP:
            g = self.game.guess.values()
        else:
            g = self.guess.values()
        for guess in g:
            if guess > .5:
                sum += 1
        return sum
game.py是运行游戏的主循环,处理各种事件
# -*- coding: utf-8 -*-
"""
Created on Sun Oct  7 10:16:24 2018
作者邮件:231469242@qq.com
作者微信公众号:PythonEducation
"""
#
#       game.py
#
#       Copyright 2010 Nolan Baker <hendersonhasselbalch@gmail.com>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

TORUS = False
OPEN_FIRST = True# false to be able to lose on first click
decided = False
LOAD_NN = True
while not decided:
    try: 
        i = raw_input("Would you like to forget? (y/n) 
")
        if i == "y": 
            LOAD_NN = False
            decided = True
        if i == "n":
            LOAD_NN = True
            decided = True
    except:
        print("No, that's not quite right")
SAVE_NN = True
SAVE_CSV = True
ASCII_OUTPUT = False
LEARN = True
DRAW = True
RECORD = False # this is really resource intensive
HUMAN = False
CHUNK = 100
SAVE_CHUNK = 1
SAVE_INT = 1
OUTPUT_TEXT = "win_pct,sq_err,pct_cor,cleared,cor_digs,inc_digs,cor_flags,inc_flags
"
DIFF = 0
DIFF_MINDS = False
AGENTS = 1

import math, os, sys, platform, pickle, random
if DRAW:
    import pygame
    from pygame.locals import *
from neural_network import *
from agent import *
try:
    from numpy import *
    import numpy.random as nrand
except:
    print "You need numpy! Ahh!"
    exit(-1)
    
    
########################################################################
# MINESWEEPER
########################################################################

class Game:
    def __init__(self, width, height, mines, draw = True, tile_size = 32, torus = False):
        self.width = width
        self.height = height
        self.mines = mines
        self.wins = 0
        self.loses = 0
        self.torus = torus
        self.guess = {}

        self.draw_board = draw
        if self.draw_board:
            pygame.init()
            self.surface = pygame.Surface((width * tile_size, height * tile_size))
            self.clock = pygame.time.Clock()
            self.tile_size = tile_size
            self.tile_dict = {}
            names = "_012345678fime"
            for name in names:
                size = (self.tile_size, self.tile_size)
                self.tile_dict[name] = pygame.transform.scale(self.loadImg(name), size)

        self.reset()

    def reset(self):
        self.goggles = 1
        self.FINISHED = False
        self.did_change = True
        self.left_clicks = 0
        self.cleared = 0
        self.correct_digs = 0
        self.incorrect_digs = 0
        self.correct_flags = 0
        self.incorrect_flags = 0
        self.towel_thrown = 0
        self.first_click = True
        self.done = False
        self.result = -1
        for i in range(self.width):
            for j in range(self.height):
                self.guess[(i,j)] = .5

        self.mine_array = {}
        for h in range(self.height):
            for w in range(self.width):
                self.mine_array[(w, h)] = 0

        self.pos_li = []
        while len(self.pos_li) != self.mines:
            rand_x = random.randint(0, self.width)
            rand_y = random.randint(0, self.height)
            pos = (rand_x, rand_y)

            if pos not in self.pos_li:
                self.pos_li.append(pos)

        for pos in self.pos_li:
            self.mine_array[pos] = 1

        self.board = {}
        for h in range(self.height):
            for w in range(self.width):
                self.upTile((w, h), "_")

    def throwTowel(self):
        self.towel_thrown = 1

    def loadImg(self, name):
        return pygame.image.load(os.path.join("images", name + ".png"))

    def upTile(self, pos, symbol):
        self.did_change = True
        self.board[pos] = symbol

        #draw stuff if drawing turned on
        if self.draw_board:
            x, y = pos
            p = (x * self.tile_size, y * self.tile_size)
            self.surface.blit(self.tile_dict[symbol], p)

    def resize(self, w, h, m):
        self.width = w
        self.height = h
        self.mines = m

    def printBoard(self):
        s = ""
        for h in range(self.height):
            for w in range(self.width):
                try:
                    s += self.board[(w, h)]
                except:
                    s += "X"
            s += "
"
        print s

    def mark(self, pos):
        # place a flag down or pull one up
        if self.board[pos] == "_":
            self.upTile(pos, "f")
            return True

        elif self.board[pos] == "f":
            self.upTile(pos, "_")
            return False

    def dig(self, pos):
        cleared = 0
        if not self.done and self.board[pos] != "f":
            self.left_clicks += 1
            "surely dig and clear can be merged"
            "things get funky with recursion"
            # clear a space and see if you win
            cleared = self.clear(pos)
            if self.isWon():
                self.wins += 1
                self.result = 1
                self.done = True
            if cleared > 0:
                self.correct_digs += 1
            elif cleared == 0:
                self.incorrect_digs += 1
            return cleared

    def clear(self, pos, auto = False):
        cleared = 0
        x = pos[0]
        y = pos[1]

        # if the space has a mine and it's not your first move
        if (self.mine_array[pos] == 1 and
            (not self.first_click or not OPEN_FIRST)):

            # go through every space on the board
            for h in range(self.height):
                for w in range(self.width):

                    # if the space is empty and flagged
                    if (self.mine_array[(w, h)] == 0 and
                        self.board[(w, h)] == "f"):

                        # mark it as incorrectly flagged
                        self.upTile((w, h), "i")
                        self.incorrect_flags += 1

                    # if the space has a mine and is flagged
                    elif (self.mine_array[(w, h)] == 1 and
                          self.board[(w, h)] == "f"):

                        # mark it as incorrectly flagged
                        self.correct_flags += 1

                    # if the space has a mine and is not flagged
                    elif (self.mine_array[(w, h)] == 1 and
                          self.board[(w, h)] == "_"):

                        # mark it as having a mine
                        self.upTile((w, h), "m")

            # mark your position as exploded
            self.upTile(pos, "e") #

            # end the game
            self.loses += 1
            self.done = True

        # if it's your first click
        if self.first_click and OPEN_FIRST:
            self.first_click = False
            if self.torus:
                w = self.width
                h = self.height
                area = [((x-1)%w, (y-1)%h), (x, (y-1)%h), ((x+1)%w, (y-1)%h),
                        ((x-1)%w, y)      , (x, y)      , ((x+1)%w, y)      ,
                        ((x-1)%w, (y+1)%h), (x, (y+1)%h), ((x+1)%w, (y+1)%h)]
            else:
                area = [(x-1, y-1), (x, y-1), (x+1, y-1),
                        (x-1, y),   (x, y),   (x+1, y),
                        (x-1, y+1), (x, y+1), (x+1, y+1)]
            count = 0
            for s in area:
                try:
                    count += self.mine_array[s]
                    self.mine_array[s] = 0
                except:
                    pass

            rh = random.randint(0, self.height - 1)
            rw = random.randint(0, self.width - 1)
            for h in range(self.height):
                for w in range(self.width):
                    p = ((w + rw) % self.width, (h + rh) % self.height)
                    if self.mine_array[p] == 0 and p not in area:
                        if count > 0:
                            self.mine_array[p] = 1
                            count -= 1
                        else:
                            break


        # if the space is empty
        if self.mine_array[pos] == 0:

            # get your neighbors
            if self.torus:
                w = self.width
                h = self.height
                area = [((x-1)%w, (y-1)%h), (x, (y-1)%h), ((x+1)%w, (y-1)%h),
                        ((x-1)%w, y)      , (x, y)      , ((x+1)%w, y)      ,
                        ((x-1)%w, (y+1)%h), (x, (y+1)%h), ((x+1)%w, (y+1)%h)]
            else:
                area = [(x-1, y-1), (x, y-1), (x+1, y-1),
                        (x-1, y),   (x, y),   (x+1, y),
                        (x-1, y+1), (x, y+1), (x+1, y+1)]
                        
            # if the space is unknown
            if self.board[pos] == "_":
                cleared += 1

                # check all neighbors for mines
                mines = 0
                for s in area:
                    try:
                        mines += self.mine_array[s]
                    except:
                        pass # invalid position


                # set your image to the number of adj. mines
                self.upTile(pos, str(mines))

            # if the space is numbered
            if self.board[pos] in "012345678":

                # check all neighbors for flags
                flags = 0
                for s in area:
                    try:
                        if self.board[s] == "f":
                            flags += 1
                    except:
                        pass # invalid position

                # if the number of flags is your number
                if ((flags == int(self.board[pos]) and not auto) or
                    int(self.board[pos]) == 0):

                    # clear all of the unknown spaces around you
                    for s in area:
                        try:
                            if self.board[s] == "_":
                                cleared += self.clear(s, True)
                        except:
                            pass # invalid position


        return cleared

    def isWon(self):
        cleared = 0
        covered = 0
        for w in range(self.width):
            for h in range(self.height):
                if (self.board[(w,h)] != "_" and
                    self.board[(w,h)] != "f" and
                    self.mine_array[(w,h)] == 0):
                        cleared += 1
                if (self.board[(w,h)] == "_" or
                    self.board[(w,h)] == "f" and
                    self.mine_array[(w,h)] == 1):
                        covered += 1
        self.cleared = cleared
        if (cleared == ((self.width * self.height) - self.mines) and
            covered == self.mines):
            self.FINISHED = True
            return True
        self.FINISHED = False
        return False

    def getErrors(self):
        sq_err = 0
        correct = 0
        for x in range(self.width):
            for y in range(self.height):
                err = abs(self.mine_array[(x,y)] - self.guess[(x,y)])
                sq_err += err ** 2
                if err < .5: correct += 1
        sq_err /= float(self.width * self.height)
        correct /= float(self.width * self.height)
        return sq_err, correct


################################################################################
# example
################################################################################

def randomGame():
    game = Game(4,4,3)
    while 1:
        game.reset()
        while not game.done:
            c = random.randint(0,1)
            x = random.randint(0, game.width - 1)
            y = random.randint(0, game.height - 1)
            if c == 0:
                game.dig((x,y))
            elif c == 1:
                game.mark((x,y))
        w, l = game.wins, game.loses
        print w,"w",l,"l",(w*100.0)/(w+l),"%"
        try: input()
        except: pass

def main():
    if DIFF == 0:
        #print "SMALL - 8x8 w/ 10 mines"
        w = 8
        h = 8
        m = 10
        t = 64
    if DIFF == 1:
        #print "MEDIUM - 16x16 w/ 40 mines"
        w = 16
        h = 16
        m = 40
        t = 32
    if DIFF == 2:
        #print "LARGE - 32x16 w/ 99 mines"
        w = 32
        h = 16
        m = 99
        t = 26
    if DIFF == 3:
        w = 8
        h = 8
        m = 15
        t = 32
    s = ""

    # create your game board
    if DRAW: os.environ['SDL_VIDEO_CENTERED'] = '1'
    game = Game(w, h, m, draw = DRAW, tile_size = t, torus = TORUS)
    count = 0
    frame = 0
    banner = "W:0 - L:0"
    if DRAW:
        pygame.display.set_caption(banner)
        screen = pygame.display.set_mode((w * t, h * t))

    # create your players
    alist = []
    for i in range(AGENTS):
        alist.append(Agent(game))
    #agent.cheat = True
    if HUMAN:
        alist[0].switch()

    ####################################################################
    # load your saved neural net from a file
    ####################################################################
    if LOAD_NN:
        if DIFF_MINDS:
            for i in range(len(alist)):
                try:
                    f = open(os.path.join("data","nn" + str(i) + ".obj"), "r")
                    alist[i].nn = pickle.load(f)
                    print "Loading Agent " + str(i) + "'s neural network."
                    f.close()
                except:
                    try:
                        f = open(os.path.join("data","nn.obj"), "r")
                        alist[i].nn = pickle.load(f)
                        for agent in alist:
                            agent.nn = alist[i].nn
                        print "Loading stock neural network."
                        f.close()
                    except:
                        #print sys.exc_info()
                        print "Couldn't load mind. Creating one."
        else:
            try:
                f = open(os.path.join("data","nn.obj"), "r")
                alist[0].nn = pickle.load(f)
                for agent in alist:
                    agent.nn = alist[0].nn
                print "Loading neural network."
                f.close()
            except:
                #print sys.exc_info()
                print "Couldn't load mind. Creating one."

    ####################################################################
    # create a log file
    ####################################################################
    if SAVE_CSV:
        csv = open(os.path.join("data", str(count) + ".csv"), "w")
        csv.write(OUTPUT_TEXT)

    # get things started
    game.running = True
    while game.running:
        for agent in alist:
            agent.clearMoves()

        ################################################################
        # AN INDIVIDUAL GAME
        ################################################################
        while not game.done:
            for agent in alist:
                agent.act()
            if ASCII_OUTPUT:
                sq_err, correct = game.getErrors()
                clear = "clear"
                if platform.system() == "Windows":
                    clear = "cls"
                os.system(clear)
                print(banner)
                print("Squared Error", sq_err)
                print("Percent Correct", correct)
                game.printBoard()
            
            if game.draw_board:
                game.clock.tick()#60) #to pace the bot
                for event in pygame.event.get() :
                    if event.type == QUIT:
                        game.running = False
                        pygame.quit ()

                    # if the keyboard is used
                    elif event.type == KEYDOWN:
                        if event.key == K_ESCAPE:
                            game.running = False
                            pygame.quit ()
                        if ((event.key == K_r and alist[0].human) or
                            (event.key == K_h and not alist[0].human)):
                            alist[0].switch()
                        if event.key == K_c:
                            alist[0].cheat = bool(1 - int(alist[0].cheat))
                        if event.key == K_g:
                            game.goggles = (game.goggles + 1) % 3


                if game.goggles == 0 or game.goggles == 1:
                    screen.blit(game.surface, (0,0))

                # DRAW AGENT'S GUESS
                # purple = mine, yellow = not mine
                # transparent = certain, opaque = not sure
                if game.goggles == 1 or game.goggles == 2:
                    temp = pygame.Surface((w,h))
                    tran = pygame.Surface((t-1, t-1))
                    for i in range(w):
                        for j in range(h):
                            g = 1 - game.guess[(i,j)]
                            g *= 255
                            tran.fill((160,g,255-g))
                            g = int(min(g, 255-g) * 2)
                            tran.set_alpha(int(g / 1.4))
                            screen.blit(tran, (i * t + 1, j * t + 1))

                ########################################################
                # DRAW EACH AGENT
                ########################################################
                for agent in alist:
                    x, y = agent.pos
                    rx, ry = random.randint(-t/3,t/3), random.randint(-t/3,t/3)
                    X, Y = x * t + t/2.0 + rx, y * t + t/2.0 + ry
                    pygame.draw.circle(screen, (0,0,0), (int(X),int(Y)), 3)

                ########################################################
                # MAKE A MOVIE
                ########################################################
                if RECORD and game.did_change:
                    print "recording"
                    old_board = copy(game.board)
                    pygame.image.save(screen, os.path.join("video", str(frame) + ".png"))
                    frame += 1
                pygame.display.flip()
                game.did_change = False

        ################################################################
        # compare agent's map of minefield to actual
        ################################################################
        sq_err, correct = game.getErrors()

        ################################################################
        # print results to file
        ################################################################
        win, lose = game.wins, game.loses
        try:
            win_pct = (win*100.0)/(win+lose)
        except: win_pct = 0

        s = (str(win_pct) + "," +
             str(sq_err) + "," +
             str(correct) + "," +
             str(game.cleared) + "," +
             str(game.correct_digs) + "," +
             str(game.incorrect_digs) + "," +
             str(game.correct_flags) + "," +
             str(game.incorrect_flags) + "
")
        if SAVE_CSV: csv.write(s)

        banner = "W: " + str(win) + " - L: " + str(lose)
        if DRAW: pygame.display.set_caption(banner)
        #print "W: ", win, " - L: ", lose
        print s

        ################################################################
        # START NEW FILE AFTER chunk ITTERATIONS
        ################################################################
        count += 1
        if SAVE_CSV and count % CHUNK == 0:
            csv.close()
            csv = open(os.path.join("data", str(count) + ".csv"), "w")
            csv.write(OUTPUT_TEXT)
        elif SAVE_CSV and not game.running:
            csv.close()

        ################################################################
        # LEARN!!!
        ################################################################
        if LEARN:
            if DIFF_MINDS:
                for agent in alist:
                    agent.learn()
            else:
                nn = alist[0].nn
                for agent in alist:
                    agent.nn = nn
                    agent.learn()
                    nn = agent.nn
                for agent in alist:
                    agent.nn = nn
                    agent.memory = alist[0].memory

        ################################################################
        # SAVE NN
        ################################################################
        if SAVE_NN and count % SAVE_INT == 0:
            if DIFF_MINDS:
                for i in range(len(alist)):
                    if i % SAVE_CHUNK == count % SAVE_CHUNK:
                        try:
                            f = open(os.path.join("data","nn" + str(i) + ".obj"), "w")
                            pickle.dump(alist[i].nn, f)
                            print "Saving neural network number " + str(i) + "."
                            f.close()
                        except:
                            #pass
                            print "Couldn't save your neural network."
            else:
                try:
                    f = open(os.path.join("data","nn.obj"), "w")
                    pickle.dump(alist[0].nn, f)
                    print "Saving your neural network."
                    f.close()
                except:
                    #pass
                    print "Couldn't save your neural network."

        ################################################################
        # RESET BOARD
        ################################################################
        game.reset()

if __name__ == '__main__':
    main()

 我们运行程序,看到下图扫雷游戏,键盘c按键是用于作弊的,就是调用代理人

运行环境是Python2.7, anaconda 

好了,就讲解到这里,游戏编程更多内容请观看我在网易云的视频教程Python菜鸟快乐游戏编程_pygame:

https://study.163.com/course/courseMain.htm?courseId=1006188025&share=2&shareId=400000000398149

我的网易云教程提供了编译好脚本,大家可以下载直接调用,边观看边演练。视频采用专业显卡录制,2k超高清,朋友们可以看清楚每一行代码的字母。

have fun!

Python入门经典(2K分辨率超清,免费,博主录制)

https://study.163.com/course/courseMain.htm?courseId=1006183019&share=2&shareId=400000000398149

原文地址:https://www.cnblogs.com/webRobot/p/9824304.html