三维圈夹游戏人机编程
林清
游戏规则:市面上有一些三维的圈夹游戏商品,最常见的一种有4层透明塑料版,每层有4*4形式的洞。两人玩时轮流把有颜色的棋子放入空着的洞中,最先将4个同色的棋子连成一条线的人赢。连线的方式有许多种,可以是水平的、垂直的,或者有角度的。
分析:4个棋子共有76条可能连成的直线。每一层,与边平行的直线有8条,再加上2条对角线,所以每一层水平的直线就有10条,4层总共就有40条。还有16条垂直线,4条长对角线,以及在8个垂直面中,
每个面上的2条对角线。
设计方案:根据下此棋子的得分来判定:(以黑棋为例)
(1):在一个空白的直线上加黑棋+1分
在只有一个白棋的直线上加黑棋+2分
在只有一个黑棋的直线上加黑棋+3分
在有两个黑棋的直线上加黑棋+4分
在有两个白棋的直线上加黑棋+5分
在有三个黑棋的直线上加黑棋 一定执行。返回成功
在有三个白棋的直线上加黑棋+100分
(2):然后,下这个点的棋子影响的直线的得分总和如果最大的就下这个点。
给出代码:
//此版本不考虑图形的显示在很多属性没有纪录:
#include<stdio.h>
#include <process.h>
#include <ctype.h>
#define MAX 100
//pMatixLine[I][7]纪录了下这个点的棋子与76条直线的那条直线有关
int pMatixLine[64][7]=
{{1,5,9,41,57,61,69},{1,6,42,63,0,0,0},{1,7,43,65,0,0,0},{1,8,10,44,58,67,70},
{2,5,45,71,0,0,0},{2,6,9,46,0,0,0},{2,7,10,47,0,0,0},{2,8,48,72,0,0,0},
{3,5,49,73,0,0,0},{3,6,10,50,0,0,0},{3,7,9,51,0,0,0},{3,8,52,74,0,0,0},
{4,5,10,53,59,62,75},{4,6,54,64,0,0,0},{4,7,55,66,0,0,0},{4,8,9,56,60,68,76},
{11,15,19,41,0,0,0},{11,16,42,69,0,0,0},{11,17,43,70,0,0,0},{11,18,20,44,0,0,0},
{12,15,45,61,0,0,0},{12,16,19,46,57,63,71},{12,17,20,47,58,65,72},{12,18,48,67,0,0,0},
{13,15,49,62,0,0,0},{13,16,20,50,59,64,73},{13,17,19,51,60,66,74},{13,18,52,68,0,0,0},
{14,15,20,53,0,0,0},{14,16,54,75,0,0,0},{14,17,55,76,0,0,0},{14,18,19,56,0,0,0},
{21,25,29,41,0,0,0},{21,26,42,70,0,0,0},{21,27,43,69,0,0,0},{21,28,30,44,0,0,0},
{22,25,45,62,0,0,0},{22,26,29,46,60,64,72},{22,27,30,47,59,66,71},{22,28,48,68},
{23,25,49,61,0,0,0},{23,26,30,50,58,63,74},{23,27,29,51,57,65,73},{23,28,52,67,0,0,0},
{24,25,30,53,0,0,0},{24,26,54,76,0,0,0},{24,27,55,75,0,0,0},{24,28,29,26,0,0,0},
{31,35,39,41,60,62,70},{31,36,42,64,0,0,0},{31,37,43,66,0,0,0},{31,38,40,44,59,68,69},
{32,35,45,72,0,0,0},{32,36,39,46,0,0,0},{32,37,40,47,0,0,0},{32,38,48,71,0,0,0},
{33,35,49,74,0,0,0},{33,36,40,50,0,0,0},{33,37,39,51,0,0,0},{33,38,52,73,0,0,0},
{34,35,40,53,58,61,76},{34,36,54,63,0,0,0},{34,37,55,65,0,0,0},{34,38,39,56,57,67,75}};
typedef enum LineStyle{empty,oneblack,towblack,threeblack,onewhite,towwhite,threewhite,mix,succeed}MyLineStyle;
typedef enum ChessmanStyle{without,chessblack,chesswhite}MyChessmanStyle;
//typedef enum ChessmanStyle{without,have}MyChessmanStyle;
typedef enum CurrentChess{black,white}MyCurrentChess;
//实现根据chess的输入改变alllinestyle影响的线条状态和allchess棋子的状态以方便下此选择的过滤
//返回1成功
int ChangeState(int IFblack,MyLineStyle AllLineStyle[76],int chess,MyChessmanStyle AllChess[64]);
//计算如果下这位置的得分数
//变成有唯一一个自己的+1
//变成有二个的+3
//变成有三个的+4
//变成有四个的+max+1
//破坏对方三个的+max
//破坏对方一个的+2
//破坏对方二个的+5
//从本来就无用的变成有用的+0
//返回-1为成功,必选
int SingleCount(int IFblack,int chess,MyLineStyle AllLineStyle[76]);
//实现选择那个方案最理想返回下的棋子位置
//返回-1无棋子可下
int ProjectSelect(int IFblack,MyLineStyle AllLineStyle[76],MyChessmanStyle AllChess[64]);
//白棋用户的输入状态
int InputChess(int IFblack,MyChessmanStyle AllChess[64]);
//打印棋盘
int chessboard(MyChessmanStyle AllChess[64]);
//打印菜单
char menu();
//人-机游戏
int mantocomputer();
//单机版人与人游戏
int mantoman();
//游戏规则
int ReadMe();
int ChangeState(int IFblack,MyLineStyle AllLineStyle[76],int chess,MyChessmanStyle AllChess[64])
{
int i;
int curline;
if (AllChess[chess]) {printf("Did not chance input ");return 0;}
// AllChess[chess]=have;
if(IFblack)//白棋下
{
AllChess[chess]=chesswhite;
for(i=0;i<7&&pMatixLine[chess][i]!=0;i++)
{
curline=pMatixLine[chess][i]-1;
switch(AllLineStyle[curline])
{
case empty:
AllLineStyle[curline]=onewhite;
break;
case oneblack:
case towblack:
case threeblack:
AllLineStyle[curline]=mix;
break;
case onewhite:
AllLineStyle[curline]=towwhite;
break;
case towwhite:
AllLineStyle[curline]=threewhite;
break;
case threewhite:
AllLineStyle[curline]=succeed;
return 1;
case mix:
break;
}
}
}
else//黑棋下
{
AllChess[chess]=chessblack;
for(i=0;i<7&&pMatixLine[chess][i]!=0;i++)
{
curline=pMatixLine[chess][i]-1;
switch(AllLineStyle[curline])
{
case empty:
AllLineStyle[curline]=oneblack;
break;
case oneblack:
AllLineStyle[curline]=towblack;
break;
case towblack:
AllLineStyle[curline]=threeblack;
break;
case threeblack:
AllLineStyle[curline]=succeed;
return 1;
case onewhite:
case towwhite:
case threewhite:
AllLineStyle[curline]=mix;
case mix:
break;
}
}
}
return 0;
}
//计算如果下这位置的得分数
//变成有唯一一个自己的+1
//变成有二个的+3
//变成有三个的+4
//变成有四个的+max+1
//破坏对方三个的+max
//破坏对方一个的+2
//破坏对方二个的+5
//从本来就无用的变成有用的+0
//返回-1为成功,必选
int SingleCount(int IFblack,int chess,MyLineStyle AllLineStyle[76])
{
int i;
int curline;
int sum=0;
if(IFblack)//白棋下
{
for(i=0;i<7&&pMatixLine[chess][i]!=0;i++)
{
curline=pMatixLine[chess][i]-1;
switch(AllLineStyle[curline])
{
case empty:
sum=sum+1;
break;
case oneblack:
sum=sum+2;
break;
case towblack:
sum=sum+5;
break;
case threeblack:
return MAX;
case onewhite:
sum=sum+3;
break;
case towwhite:
sum=sum+4;
break;
case threewhite:
return -1;
case mix:
break;
}
}
}
else//黑棋下
{
for(i=0;i<7&&pMatixLine[chess][i]!=0;i++)
{
curline=pMatixLine[chess][i]-1;
switch(AllLineStyle[curline])
{
case empty:
sum=sum+1;
break;
case oneblack:
sum=sum+3;
break;
case towblack:
sum=sum+4;
break;
case threeblack:
return -1;
case onewhite:
sum=sum+2;
break;
case towwhite:
sum=sum+5;
break;
case threewhite:
sum=MAX;
break;
case mix:
break;
}
}
}
return sum;
}
//实现选择那个方案最理想返回下的棋子位置
//返回-1无棋子可下
int ProjectSelect(int IFblack,MyLineStyle AllLineStyle[76],MyChessmanStyle AllChess[64])
{
int downchess=-1;
int maxmark=0;
int currentmark=0;
for(int i=0;i<64;i++)
{
if(AllChess[i]!=without) continue;
currentmark=SingleCount(IFblack,i,AllLineStyle);
if(currentmark==-1) return i;
if(currentmark>maxmark)
{
downchess=i;
maxmark=currentmark;
}
}
return downchess;
}
//白棋用户的输入状态
int InputChess(int IFblack,MyChessmanStyle AllChess[64])
{
int z,x,y;
int chess;
do
{
chessboard(AllChess);
if(IFblack==black)printf("黑棋下%c(层,行,列):",1);
else printf("白棋下%c(层,行,列):",2);
scanf("%d,%d,%d",&z,&y,&x);
chess=(z-1)*16+y*4+x;
}while(z>4||z<1||y>3||y<0||x>3||x<0||AllChess[chess]!=without);
return chess;
}
//打印棋盘
int chessboard(MyChessmanStyle AllChess[64])
{
int i,j,m,current=0;
system("cls");
printf(" 三维圈夹游戏\n");
printf("|(一)| |(二)| |(三)| |(四)|\n");
printf("|0123| |0123| |0123| |0123|\n");
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%d",i);
for(m=0;m<4;m++)
{
switch(AllChess[current++])
{
case without: printf(" ");break;
case chessblack:printf("%c",1);break;
case chesswhite:printf("%c",2);break;
}
}
printf("| ");
current=current+12;
}
printf("\n");
current=(i+1)*4;
}
return 1;
}
//打印菜单
char menu()
{
char ch;
do
{
system("cls");
printf("(J)人机模式\n");
printf("(M)人-人模式\n");
printf("(R)游戏规则\n");
printf("(F)返回\n");
printf("请选择你所要的操作(J,M,R,F):");
scanf("%c",&ch);
ch=toupper(ch);
}while(ch!='J'&&ch!='M'&&ch!='R'&&ch!='R');
return ch;
}
//人-机游戏
int mantocomputer()
{
MyCurrentChess currentchess=black;
MyLineStyle line[76];
MyChessmanStyle chess[64];
int GetChess=-1;
int i;
for(i=0;i<76;i++) line[i]=empty;
for(i=0;i<84;i++) chess[i]=without;
// chessboard(chess);
do
{
if((GetChess=InputChess(currentchess,chess))==-1) {printf("Input error or exit\n");break;}
if(ChangeState(currentchess,line,GetChess,chess)) {chessboard(chess);printf("black win\n");break;}
currentchess=white;
if((GetChess=ProjectSelect(currentchess,line,chess))==-1){printf("a draw in chess\n");break;}
if(ChangeState(currentchess,line,GetChess,chess)) {chessboard(chess);printf("white win\n");break;}
currentchess=black;
chessboard(chess);
}while(1);
return 1;
}
//单机版人与人游戏
int mantoman()
{
return 1;
}
//游戏规则
int ReadMe()
{
return 1;
}
int main()
{
char ch;
do
{
ch=menu();
switch(ch)
{
case 'J':
mantocomputer();
break;
case 'M':
mantoman();
break;
case 'R':
ReadMe();
break;
case 'F':
break;
}
}while(ch=='F');
printf("\n欢迎使用\n");
system("pause");
return 1;
}
//备注:第一次发稿,请大家原谅。