python-2048

主要看了参考了一下

http://blog.csdn.net/xiaohui_hubei/article/details/25333775

他将思路已经写的很清楚了


主要在他的基础上做了两个修改

1,由python3切到python2.7

2,修改出现例如(4,4,8,0)这样的情况,得分不合理的情况


# -*- coding:UTF-8 -*-
#!/usr/bin/python2
 
import random
 
v = [[0, 0, 0, 0],
     [0, 0, 0, 0],
     [0, 0, 0, 0],
     [0, 0, 0, 0]]
 
def display(v, score):
	print "%4d	%4d	%4d	%4d"	%	(v[0][0], v[0][1], v[0][2], v[0][3])
	print "%4d	%4d	%4d	%4d"	%	(v[1][0], v[1][1], v[1][2], v[1][3])
	print "%4d	%4d	%4d	%4d"	%	(v[2][0], v[2][1], v[2][2], v[2][3])
	print "%4d	%4d	%4d	%4d"	%	(v[3][0], v[3][1], v[3][2], v[3][3])
 
def init(v):
	for i in range(4):
		v[i] = [random.choice([0, 0, 0, 2, 2, 4]) for x in range(4)]

def align(vList, direction):
	for i in range(vList.count(0)):
		vList.remove(0)
	zeros = [0 for x in range(4 - len(vList))]
	if direction == 'left':
		vList.extend(zeros)
	else:
		vList[:0] = zeros

def addSame(vList, direction):
	score = 0
	if direction == 'left':
		for i in [0, 1, 2]:
			align(vList, direction)
			if vList[i] == vList[i+1] != 0:
				vList[i] *= 2
				vList[i+1] = 0
				score += vList[i]
		return {'bool':True, 'score':score}
	else:
		for i in [3, 2, 1]:
			align(vList, direction)
			if vList[i] == vList[i-1] != 0:
				vList[i] *= 2
				vList[i-1] = 0
				score += vList[i]
		return {'bool':True, 'score':score}
	return {'bool':False, 'score':score}

def handle(vList, direction):
	totalScore = 0
	result = addSame(vList, direction)
	return totalScore
	 
def operation(v):
	totalScore = 0
	gameOver = False
	direction = 'left'
	op = raw_input('operator:')
	if op in ['a','A']:
		direction = 'left'
		for row in range(4):
			totalScore += handle(v[row], direction)
	elif op in ['d','D']:
		direction = 'right'
		for row in range(4):
			totalScore += handle(v[row], direction)
	elif op in ['w', 'W']:
		direction = 'left'
		for col in range(4):
			vList = [v[row][col] for row in range(4)]
			totalScore += handle(vList, direction)
			for row in range(4):
				v[row][col] = vList[row]
	elif op in ['s', 'S']:
		direction = 'right'
		for col in range(4):
			vList = [v[row][col] for row in range(4)]
			totalScore += handle(vList, direction)
			for row in range(4):
				v[row][col] = vList[row]
	else:
		print "Invalid input,please enter a charactor in [W,S,A,D] or the lower"
		return {'gameOver':gameover,'score':totalScore}

	N = 0
	for q in v:
		N += q.count(0)

	if N == 0:
		gameOver = True
		return {'gameover':gameOver,'score':totalScore}
	
	num = random.choice([2,2,2,4])
	k = random.randrange(1, N+1)
	n = 0

	for i in range(4):
		for j in range(4):
			if v[i][j] == 0:
				n += 1
				if n == k:
					v[i][j] = num
					break			

	return {'gameOver':gameOver, 'score':totalScore}
	

init(v)
score = 0
print "Input:W(Up) S(Down) A(Left) D(Right), press <CR>."
while True:
	display(v, score)
	result = operation(v)
	if result['gameOver'] == True:
		print "Game Over, You failed!"
		print "Your total score %d" % (score)
	else:
		score += result['score']
		if score >= 2048:
			print "Game Over, You Win!!!"
			print "Your total score: %d" % (score)





附上一个别人写的2048 ai的代码,跑了一下,得分5万-11万,没怎么看懂,有同事写2048 AI程序,能得80万分。
<pre name="code" class="cpp">

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <sys/time.h>
#include <time.h>

#define AUTO

#define SIZE (4)
typedef int board_t[SIZE][SIZE];
struct hash_elem {
    int hash;
    int depth;
    double value;
};

enum input {
    LEFT = 0,
    RIGHT = 1,
    UP = 2,
    DOWN = 3,
    QUIT = 4
};

/* Static mappings & initialzation ***********************************/

/* Weight of each value */
int value_weight[16];
/* Mapping from value to power of 2 form */
int value_real[16];
/* Default search depth for each #zero-blocks */
int depth_map[] = {6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4};

/* Weight map of cells */
static const board_t cell_weight = {
    {17, 13, 11, 10},
    {13, 10,  9,  9},
    {11,  9,  8,  8},
    {10,  9,  8,  8}
};

/* Used for hash table */
static const board_t primes = {
    {22189, 28813, 37633, 43201}, 
    {47629, 60493, 63949, 65713}, 
    {69313, 73009, 76801, 84673}, 
    {106033, 108301, 112909, 115249}
};
    
void init() {
    int i;
    int cur_weight = 1;
    int cur_real = 2;
    for (i = 1; i < 16; i++) {
        value_weight[i] = cur_weight;
        value_real[i] = cur_real;
        cur_weight *= 3;
        cur_real *= 2;
    }
}

/* Util Functions *****************************************************/
long gettime() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 * 1000 + tv.tv_usec;
}

void draw_grid(int y, int x) {
    mvprintw(y++, x,    "#####################################");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#-----------------------------------#");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#-----------------------------------#");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#-----------------------------------#");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#        |        |        |        #");
    mvprintw(y++, x,    "#####################################");
    mvprintw(y+2, x,    "Control: wasd  Exit: q");
}


void board_dump(board_t b, int y, int x) { 
    int i, j;
    draw_grid(y, x);
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            if (b[i][j])
                mvprintw(i * 4 + 2 + y, j * 9 + 3 + x, "%d", value_real[b[i][j]]);
        }
    }
}

int board_count_zero(board_t b) {
    int cnt = 0;
    int i, j;
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            if (b[i][j] == 0)
                cnt++;
        }
    }
    return cnt;
}

void board_clear(board_t b) {
    int i, j;
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            b[i][j] = 0;
        }
    }
}

int board_hash(board_t b) {
    int i, j;
    int hash = 0;
    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            hash += b[i][j] * primes[i][j];
        }
    }
    return hash;
}

void board_rnd_gen_cell(board_t b) {
    int i, j;
    int cnt = board_count_zero(b);
    int gen = random() % cnt;
    int n = (random() % 10) == 0 ? 2 : 1;

    cnt = 0;    

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            if (b[i][j] == 0) {
                if (cnt == gen) {
                    b[i][j] = n;
                    return;
                }
                cnt++;
            }
        }
    }
}

void delay() {
    struct timespec t;
    t.tv_sec = 0;
    t.tv_nsec = 10000000;
    nanosleep(&t, NULL);
}

/* Performance statistic */
long stat_time[16];
long stat_count[16]; 
void stat(int depth, long time) {
    stat_count[depth]++;
    stat_time[depth] += time;
}

void stat_dump() {
    int i;
    int line = 0;
    mvprintw(25 + line++, 8, "Performance Stat");
    for (i = 0; i < 16; i++) {
        if (!stat_count[i])
            continue;
        mvprintw(25 + line++, 8, "[Depth %d] %ld us * %d times",
            i, stat_time[i] / stat_count[i], stat_count[i]);
    }   
}

/* Game logic: Move to a direction **************************************************/

/* Return score earned, return 1 if moved with zero score */
#define movefunc(src_cell, combine_cell, nocombine_cell)\
{\
    int i, j = 0;\
    int moved = 0;\
    int score = 0;\
    for (i = 0; i < SIZE; i++) {\
        int last = 0;\
        int j2 = 0;\
        for (j = 0; j < SIZE; j++) {\
            int v = src_cell;\
            if (v == 0) {\
                continue;\
            }\
            if (v == last) {\
                last = 0;\
                combine_cell = v + 1;\
                score += value_real[v + 1];\
            } else {\
                if (j2 < j)\
                    moved = 1;\
                last = v;\
                nocombine_cell = v;\
                j2++;\
            }\
        }\
    }\
    return score ? score : moved;\
}

#define REVERSE(i) (SIZE - 1 - (i))



int move_left(board_t src, board_t dst) {
    movefunc(src[i][j], dst[i][j2 - 1], dst[i][j2]);
}

int move_right(board_t src, board_t dst) {
    movefunc(src[i][REVERSE(j)], dst[i][REVERSE(j2 - 1)], dst[i][REVERSE(j2)]);
}

int move_up(board_t src, board_t dst) {
    movefunc(src[j][i], dst[j2 - 1][i], dst[j2][i]);
}

int move_down(board_t src, board_t dst) {
    movefunc(src[REVERSE(j)][i], dst[REVERSE(j2 - 1)][i], dst[REVERSE(j2)][i]);
}


/* AI-related functions **************************************************/
double value(board_t b, int depth, int *choice, double max);

/* Immediate value score estimation for a board */
int imm_value(board_t b) {
    int i, j;
    int result = 0;

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            result += value_weight[b[i][j]] * cell_weight[i][j];
        }
    }
    return result;
}

#define HASH_SIZE (35317) 
struct hash_elem vcache[HASH_SIZE];
void cache_board_value(board_t b, int depth, double value) {
    int hash = board_hash(b);
    int index = hash % HASH_SIZE;
    vcache[index].hash = hash;
    vcache[index].value = value;
    vcache[index].depth = depth;
}

int qcnt;
int qmiss;
double query_board_value(board_t b, int depth) {
    int hash = board_hash(b);
    int index = hash % HASH_SIZE;
    qcnt++;
    if (vcache[index].hash == hash && vcache[index].depth >= depth) {
        return vcache[index].value;
    }
    qmiss++;
    return -1;
}

/* Generate 2/4 at every posible position, return the average value score 
 * b        : the board
 * depth    : depth of the recursive search
 * max      : current maximum value score
 * sampled  : sample rate, 0 means no sample
 */
double rnd_value(board_t b, int depth, double max, int sampled) {
    int i, j;
    int cnt = 0;
    double sum = 0;
    static int scnt = 0;

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            /* Check zero */
            if (b[i][j])
                continue;

            /* Do sampling to reduce computation if needed */
            if (sampled) {
                scnt++;
                if(scnt % sampled)
                    continue;
            }
            cnt += 9;
            b[i][j] = 1;
            sum += 9 * value(b, depth, NULL, max);
            /* We do not take random 4 into consideration as it is rare */
            if (depth >= 5) {
                cnt += 1;
                b[i][j] = 2;
                sum += value(b, depth, NULL, max);
            }
            /**/
            b[i][j] = 0;
        }
    }
    return sum / cnt;
}

/* Return the value score for given board, zero score means died 
 * b        : the board
 * depth    : depth of the recursive search
 * choice   : used to return the final choise of movement
 * max      : current maximum value score
 */
double value(board_t b, int depth, int *choice, double max) {
    /* Estimate the value score */
    int estimate = imm_value(b);

    /* Decrease depth if estimation is too low */
    if (estimate < max * 0.7)
        depth--;

    /* Return estimation at level 0 */
    if (depth <= 0)
        return estimate;

    /* Adjust next depth according to depth_map */ 
    int next_depth = depth - 1;    
    if (depth > 3) {
        int zeros = board_count_zero(b);
        if (next_depth > depth_map[zeros])
            next_depth--; 
    } 
    
    int i;
    int moved[4];
    double maxv = 0;
    board_t tmp[4] = {0};
    int my_choice = QUIT; /* Default choice */

    if (!choice) {
        double v = query_board_value(b, depth);
        if (v >= 0)
            return v;
    }
    
    moved[LEFT] = move_left(b, tmp[LEFT]);
    moved[RIGHT] = move_right(b, tmp[RIGHT]);
    moved[UP] = move_up(b, tmp[UP]);
    moved[DOWN] = move_down(b, tmp[DOWN]);

    /* Estimate the maximum value score */
    if (depth > 2)
    for (i = 0; i < 4; i++) {
        int v = imm_value(tmp[0]);
        max = v > max ? v : max;
    }   
    
    /* Try all the four direction */ 
    for (i = 0; i < 4; i++) {
        int c;
        if (!moved[i])
            continue;
        int sample = 0; //depth < 3 ? 3 : 1;
        double v = rnd_value(tmp[i], next_depth, max, sample);
        if (v > maxv) {
            my_choice = i;
            maxv = v;
            max = maxv;
        }
    }

    if (choice)
        *choice = my_choice;
   
    cache_board_value(b, depth, maxv); 
    return maxv;
}

/* Game logic: Control and Interface *************************************/
static int get_AI_input(board_t b) {
    int choice;
    int zeros = board_count_zero(b);

    long start = gettime();
    double v = value(b, depth_map[zeros], &choice, 0);
    long timeval = gettime() - start;
    stat(depth_map[zeros], timeval);

    return choice;
}

static int get_keyboard_input() {
    char c;
    while(1) {
        //c = getchar();
        c = getch();
        switch(c) {
            case 'w': return UP;
            case 'a': return LEFT;
            case 's': return DOWN;
            case 'd': return RIGHT;
            case 'q': return QUIT;
        }
    }
}

int auto_play = 0;
int suggestion = 0;

void game_loop() {

    board_t a = {0};
    board_t b = {0};
    board_t *cur;
    board_t *next;

    int input;
    int AI_input;
    int score = 0;
    
    cur = &a;
    next = &b;

    board_rnd_gen_cell(*cur);
    
    while (1) {
        clear();
        
        /* Draw the board */
        board_dump(*cur, 4, 8);
        // stat_dump(); 
        
        /* AI computation */
        if (auto_play || suggestion) {
            AI_input = get_AI_input(*cur);
            const char *move_text[] = {"Left", "Right", "Up", "Down", "Game Over"};
            mvprintw(1, 8, "Suggest: %s", move_text[AI_input]);
        }
        mvprintw(2, 8, "Score: %d", score);
        
        /* Update screen */
        refresh();
        
        /* Get input */
        if (auto_play) {
            input = AI_input;
        } else {
            input = get_keyboard_input();
        }

        int moved = 0;
        switch(input) {
            case UP:
                moved = move_up(*cur, *next); break;
            case LEFT:
                moved = move_left(*cur, *next); break;
            case DOWN:
                moved = move_down(*cur, *next); break;
            case RIGHT:
                moved = move_right(*cur, *next); break;
            case QUIT:
                return;
            default:
                continue;
        }

        if (!moved)
            continue;
       
        if (moved != 1)
            score += moved;
 
        /* Generate new cell */
        board_rnd_gen_cell(*next);

        /* Switch cur and next */ 
        board_t *temp = cur;
        cur = next;
        next = temp; 
        board_clear(*next);
    }

}

int main(int argc, char *argv[]) {
    int opt;
    while ((opt = getopt(argc, argv, "as")) != -1) {
        switch (opt) {
            case 'a':
                auto_play = 1;
                break;
            case 's':
                suggestion = 1;
                break;
            default: /* '?' */
                fprintf(stderr, "Usage: %s [-a] [-s]\r\n", argv[0]);
                fprintf(stderr, "-a:  Let AI play the game\r\n");
                fprintf(stderr, "-s:  Display AI suggestion\r\n");
                exit(EXIT_FAILURE);
        }

    }


    init();
    srandom(time(NULL)); 
    initscr();
    noecho();
    
    game_loop();
    
    refresh();
    endwin();
    return 0;
}


 
对应的makefile
<pre name="code" class="cpp">CC=gcc
CFLAGS=-g -O3 -lncurses

.PHONY : all
all: 2048.c 
	$(CC) 2048.c -o 2048 $(CFLAGS)


 
对应的readme
<pre name="code" class="cpp">2048-AI
=======

2048 game with a smart AI that can reach the 8192 block.
Here is my results of 10 consecutive runs:

    Max Block      Score 
    ====================
    8192           167032
    4096           76620
    8192           113780
    8192           112272
    8192           128884
    2048           36112
    8192           132784
    4096           80744
    2048           32032
    4096           80772

Compile & Play
-------

    make
    ./2048     <-- Normal mode
    ./2048 -s  <-- Play with AI suggestion
    ./2048 -a  <-- Watch AI plays it. Good luck!

 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值