用c++做.docx

上传人:b****3 文档编号:10510649 上传时间:2023-05-26 格式:DOCX 页数:15 大小:18.40KB
下载 相关 举报
用c++做.docx_第1页
第1页 / 共15页
用c++做.docx_第2页
第2页 / 共15页
用c++做.docx_第3页
第3页 / 共15页
用c++做.docx_第4页
第4页 / 共15页
用c++做.docx_第5页
第5页 / 共15页
用c++做.docx_第6页
第6页 / 共15页
用c++做.docx_第7页
第7页 / 共15页
用c++做.docx_第8页
第8页 / 共15页
用c++做.docx_第9页
第9页 / 共15页
用c++做.docx_第10页
第10页 / 共15页
用c++做.docx_第11页
第11页 / 共15页
用c++做.docx_第12页
第12页 / 共15页
用c++做.docx_第13页
第13页 / 共15页
用c++做.docx_第14页
第14页 / 共15页
用c++做.docx_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

用c++做.docx

《用c++做.docx》由会员分享,可在线阅读,更多相关《用c++做.docx(15页珍藏版)》请在冰点文库上搜索。

用c++做.docx

用c++做

用c++做2048的一种方法

X.P.Y

本文绝对原创。

需要的知识:

c++

能够实现的功能:

手动或自动进行2048游戏。

AI算法:

一次计算有4个方向,预测三步需要64个状态,但是最后一步可以退回,所以需要开int[16][16],通过一次枚举方向来算评估分,并用评估分最大的方向作为下一次移动的方向。

遗憾的是,本算法到达2048概率并不高。

首先,如何实现一个2048界面。

准备函数:

voidgotoxy(intx,inty)函数:

(TC、BC自带该函数)

文件头:

#include

#include

函数代码:

voidgotoxy(intx,inty){

COORDc;c.X=x;c.Y=y;

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);

}

int&at(int*pn,intx,inty=-1,boolreverse=false):

(实现这个函数的目的是让一维数组变为二维数组,其中pn是一维数组地址,x为行,y为列(如果是默认参数-1则返回一维数组),是否颠倒xy位置是为了以后写代码比较方便,在后面给出具体解释)

函数代码:

int&at(int*pn,intx,inty=-1,boolreverse=false){

returnreverse?

(~y?

pn[x*4+y]:

pn[x]):

(~y?

pn[y*4+x]:

pn[x]);

}

voidrandom_insert(int*pn)

(向棋盘内空白处插入一个数2或4,其中插入2的概率为90%)

文件头:

#include

函数代码:

voidrandom_insert(int*pn){

intdataCount=0;

for(inti=0;i<16;i++)

if(pn[i])

dataCount++;

if(dataCount==16)

return;

intindex=rand()%(16-dataCount);

intiScan=0;

while(pn[iScan]||index--)iScan++;

pn[iScan]=(rand()%10)?

2:

4;

}

解释:

dataCount:

统计棋盘内非零个数,如果非零数为16证明不能插入数了,返回。

如何随机插入呢?

首先取得空白数目:

16-dataCount,在0--空白数目-1之间取得一个随机数记为index,重新扫描棋盘,每次遇到空白时index自减1,当找到一个空白,并且index=0时,插入这个数。

voidinitialize(intn=3)

(初始化棋盘(棋盘为全局变量一维数组inttable[16]),其中的n代表初始化后棋盘内最初有几个数)

文件头:

#include

#include

函数代码:

voidinitialize(intn=3){

srand(time(0));

memset(table,0,16*sizeof(int));

Score=Max_number=0;

while(n--)random_insert(table);

}

解释:

memset(table,0,16*sizeof(int))将table地址往后16*sizeof(int)个字节赋值为0。

voidprint()

(打印棋盘。

不用清屏的原因是清屏会闪一下)

文件头:

#include

函数代码:

voidprint(){

gotoxy(0,0);

printf("2048-GameTabledesignedbyX.P.Y\nScore:

%d\n\n\n",Score);//x=1

for(inti=0;i<16;i++){

gotoxy((i%4+1)*5+1,(i/4+1)*2+1);

printf("%d",table[i]);

}

gotoxy(0,11);

}

boolisConinue(int*pn)

(每次操作会在一个while循环里进行,用本函数判断是否游戏结束。

直接放在while判断即可)

函数代码:

boolisConinue(int*pn=table){

intdataCount=0;

for(inti=0;i<16;i++)if(at(pn,i,-1,false))dataCount++;

returndataCount<16||cur_direction(table,0,true)||cur_direction(table,2,true);

}

boolcanMove(int*pn,intdirection)

(注:

这里的direction只有0、1两个值,分别代表横向、纵向。

本函数主要为了判断下一步是否可以横向走或纵向走。

函数代码:

boolcanMove(int*pn,intdirection){

for(inti=0,sum=0;i<4;i++){

for(intj=0;j<4;j++){

if(!

at(pn,i,j,direction==0))returntrue;

if(j&&at(pn,i,j,direction==0)==at(pn,i,j-1,direction==0))returntrue;

}

}

returnfalse;

}

接下来便是本程序的核心:

移动函数:

intcur_direction(int*pn,intdirect,boolvisual=false,int*callcount=NULL,int*squareCount=NULL,boolnoinsert=false)

(解释:

pn棋盘,这里之所以不用table是因为如果有ai预测下一步算法时,会另外开辟一段空间进行虚拟操作,此时的pn就不是table了。

参数解释:

direct:

0、向上移动

1、向下移动

2、向左移动

3、向右移动

visual:

是否为虚拟操作(操作只计算数据,不改变棋盘)

callcount:

特殊参数,如果存在该指针,一轮操作结束后指针指向的int将会被赋值为本次操作消除方块的个数。

squareCount:

特殊参数,如果存在该指针,一轮操作结束后指针指向的int将会被赋值为本次操作结束后方块的数据平整性(每个元素与同行、同列的临近元素呈2倍关系的程度)

noinsert:

如果值为真,则操作结束后不会自动插入随机方块。

函数代码:

intcur_direction(int*pn,intdirect,boolvisual=false,int*callcount=NULL,int*squareCount=NULL,boolnoinsert=false){

int_score=0,sum=0,square=0,flag=1;

boolisReverse=direct%2==0;

for(intiLine=0;iLine<4;iLine++){

vectorline;

for(inti=(isReverse?

0:

3);i!

=(isReverse?

4:

-1);i+=(isReverse?

1:

-1)){

if(at(pn,iLine,i,direct>1))line.push_back(at(pn,iLine,i,direct>1));

flag=1;

while(flag){

flag=0;

for(intk=1;k

if(line[k-1]==line[k]){

line[--k]*=2;

_score+=line[k];

if(Max_number

line.erase(line.begin()+k+1);

flag++;

}

sum+=flag;

}

}

if(!

visual)

for(inti=(isReverse?

0:

3);i!

=(isReverse?

4:

-1);i+=(isReverse?

1:

-1)){

if(line.empty())at(pn,iLine,i,direct>1)=0;

else{

at(pn,iLine,i,direct>1)=line[0];

line.erase(line.begin());

}

}

for(inti=1;i

if(line[i-1]*2==line[i]||line[i-1]==2*line[i])

square+=line[i]-line[i-1];

}

if(callcount)(*callcount)=sum;

if(squareCount)(*squareCount)=abs(square);

if((!

visual)&&(!

noinsert))random_insert(pn);

return_score;

}

解释:

大体思路:

本函数的返回值是本轮结束后得到的分数,函数采用vector可变数组来记录本次操作的一行或一列中非零个数,并在vector内完成相同方块消除操作,并在操作完成后重新赋值给原棋盘。

voidgameJudge()

(游戏函数,完成人机交互)

函数代码:

voidgameJudge(){

initialize();

while(isConinue()){

print();

switch(getch()){

case87:

case119:

case72:

Score+=cur_direction(table,0);break;

case83:

case115:

case80:

Score+=cur_direction(table,1);break;

case65:

case97:

case75:

Score+=cur_direction(table,2);break;

case68:

case100:

case77:

Score+=cur_direction(table,3);break;

}

}

}

到这里,已经完成了一个2048游戏的界面以及各种功能。

以下是ai自动游戏的算法,并不太成熟:

voidai_judge(intnloop=1)

(nloop:

玩几次)

函数代码:

voidai_judge(intnloop=1){

while(nloop--){

initialize();

while(isConinue()){

Score+=cur_direction(table,ai_calculate());

print();

}

}

}

ai算法的核心:

intai_calculate()

(该函数的返回值是理论上最好的下一步方向)

函数代码:

intai_calculate(){

boolcanv=canMove(table,0),canh=canMove(table,1);

if(!

(canv&&canh))returncanv?

2:

0;

intsum[4]={0},score[4]={0},square[4]={0},ai_table[16][16];

inttmp_sum,tmp_square,index=0,maxScore=-1,curScore=0;

for(inti=0;i<4;i++){

for(intk=0;k<4;k++){

memcpy(ai_table[i*k],table,sizeof(int)*16);

score[i]=cur_direction(ai_table[i*k],i,false,sum+i,square+i);

score[i]+=0.8*cur_direction(ai_table[i*k],k,false,&tmp_sum,&tmp_square,true);

sum[i]+=0.8*tmp_sum;

square[i]+=0.8*tmp_square;

for(intj=0;j<4;j++){

score[i]+=0.4*cur_direction(ai_table[i*k],j,true,&tmp_sum,&tmp_square,true);

sum[i]+=0.4*tmp_sum;

square[i]+=0.4*tmp_square;

}

curScore=2*score[i]+sum[i];

if(maxScore

}

}

returnindex;

}

解释:

本函数会对向下3步进行评估,并用评估分来作为下一步最优方向的依据。

由于下一步与下两步的得分是不确定的,因此不能有大于1的权值。

最终本程序的代码为:

#include

#include

#include

#include

#include

#include

#include

usingnamespacestd;

inttable[16]={0},Score=0,Max_number=0;

boolallprint=true;

int&at(int*pn,intx,inty=-1,boolrev=false){

returnrev?

(~y?

pn[x*4+y]:

pn[x]):

(~y?

pn[y*4+x]:

pn[x]);

}

boolcanMove(int*pn,intdirection){

for(inti=0,sum=0;i<4;i++){

for(intj=0;j<4;j++){

if(!

at(pn,i,j,direction==0))returntrue;

if(j&&at(pn,i,j,direction==0)==at(pn,i,j-1,direction==0))returntrue;

}

}

returnfalse;

}

voidgotoxy(intx,inty){

COORDc;c.X=x;c.Y=y;

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);

}

voidrandom_insert(int*pn){

intdataCount=0;

for(inti=0;i<16;i++)

if(pn[i])

dataCount++;

if(dataCount==16)

return;

intindex=rand()%(16-dataCount);

intiScan=0;

while(pn[iScan]||index--)iScan++;

pn[iScan]=(rand()%10)?

2:

4;

}

intcur_direction(int*pn,intdirect,boolvisual=false,int*callcount=NULL,int*squareCount=NULL,boolnoinsert=false){

int_score=0,sum=0,square=0,flag=1;

boolisReverse=direct%2==0;

for(intiLine=0;iLine<4;iLine++){

vectorline;

for(inti=(isReverse?

0:

3);i!

=(isReverse?

4:

-1);i+=(isReverse?

1:

-1)){

if(at(pn,iLine,i,direct>1))line.push_back(at(pn,iLine,i,direct>1));

flag=1;

while(flag){

flag=0;

for(intk=1;k

if(line[k-1]==line[k]){

line[--k]*=2;

_score+=line[k];

if(Max_number

line.erase(line.begin()+k+1);

flag++;

}

sum+=flag;

}

}

if(!

visual)

for(inti=(isReverse?

0:

3);i!

=(isReverse?

4:

-1);i+=(isReverse?

1:

-1)){

if(line.empty())at(pn,iLine,i,direct>1)=0;

else{

at(pn,iLine,i,direct>1)=line[0];

line.erase(line.begin());

}

}

for(inti=1;i

if(line[i-1]*2==line[i]||line[i-1]==2*line[i])

square+=line[i]-line[i-1];

}

if(callcount)(*callcount)=sum;

if(squareCount)(*squareCount)=abs(square);

if((!

visual)&&(!

noinsert))random_insert(pn);

return_score;

}

boolisConinue(int*pn=table){

intdataCount=0;

for(inti=0;i<16;i++)if(at(pn,i,-1,false))dataCount++;

returndataCount<16||cur_direction(table,0,true)||cur_direction(table,2,true);

}

voidprint(){

if(!

allprint)return;

gotoxy(0,0);

printf("2048-GameTabledesignedbyX.P.Y\nScore:

%d\n\n\n",Score);//x=1

for(inti=0;i<16;i++){

gotoxy((i%4+1)*5+1,(i/4+1)*2+1);

printf("%d",table[i]);

}

gotoxy(0,11);

}

intai_calculate(){

boolcanv=canMove(table,0),canh=canMove(table,1);

if(!

(canv&&canh))returncanv?

2:

0;

intsum[4]={0},score[4]={0},square[4]={0},ai_table[16][16];

inttmp_sum,tmp_square,index=0,maxScore=-1,curScore=0;

for(inti=0;i<4;i++){

for(intk=0;k<4;k++){

memcpy(ai_table[i*k],table,sizeof(int)*16);

score[i]=cur_direction(ai_table[i*k],i,false,sum+i,square+i);

score[i]+=0.8*cur_direction(ai_table[i*k],k,false,&tmp_sum,&tmp_square,true);

sum[i]+=0.8*tmp_sum;

square[i]+=0.8*tmp_square;

for(intj=0;j<4;j++){

score[i]+=0.4*cur_direction(ai_table[i*k],j,true,&tmp_sum,&tmp_square,true);

sum[i]+=0.4*tmp_sum;

square[i]+=0.4*tmp_square;

}

curScore=2*score[i]+sum[i];

if(maxScore

}

}

returnindex;

}

voidinitialize(intn=3){

memset(table,0,16*sizeof(int));

Score=Max_number=0;

while(n--)random_insert(table);

}

voidgameJudge(){

initialize();

while(isConinue()){

print();

switch(getch()){

case87:

case119:

case72:

Score+=cur_direction(table,0);break;

case83:

case115:

case80:

Score+=cur_direction(table,1);break;

case65:

case97:

case75:

Score+=cur_direction(table,2);break;

case68:

case100:

case77:

Score+=cur_direction(table,3);break;

}

}

}

voidai_judge(intnloop=1){

while(nloop--){

initialize();

while(isConinue()){

Score+=cur_direction(table,ai_calculate());

print();

}

if(allprint)printf("MaxNumber:

%d\n",Max_number);

}

}

intmain(){

srand(time(0));

gameJudge();

return0;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2