C语言初学者的第一个小项目,瑕疵很多,欢迎大佬指点 棋盘绘制部分参考大佬文章:C语言实现的五子棋
效果图: 大致说一下关键点:
1.判断输赢
1)一场游戏的结果只会被一个新落下的棋子改变(貌似废话),所以这里并不需要每次都遍历棋盘所有棋子,只需要判断新落下棋子是否会在四个方向上形成5连珠的情况.
2)分为 上,下,左,右,左上,右下,右上,左下,8个方向分别判断连续的个数,(其中,上,下方向 使用同一个变量进行计数,最后表示纵向连续的数量,其他的几个方向也如此),最后取四个计数的最大值,如果大于等于4,即表示5连珠.
2.电脑下棋算法(一点点小小的想法)
模拟一下真人下棋的思维,首先会先看自己棋子下哪个位置棋子连起来的多,其次看哪个位置对手连起来的多,如果对手棋子连续很多,就要进行防守.
程序直接计算每个位置 自己棋子棋子连续的数量和对方棋子连续数量之和,结果最大的,作为棋子最佳落点. 但是这样计算出来的效果会让程序傻乎乎的在该防守的时候不知道防守.
于是我把公式中对方棋子数量乘以两倍,这样即使我有两个棋子连续,对方只有一个棋子,那也会去防守对方.
这样的效果是至少能让电脑陪你玩很多轮,有了一定的游戏体验.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#define SIZE 20
#define RIGHT (i>=2&&i<=SIZE-1&&j>=2&&j<=SIZE-1)
int board[SIZE][SIZE]={0};
int computer=0;
void print_board(){
printf(" ");
for(int i=0;i<SIZE;i++){
printf("%d",i+1);
if(i<8)
printf(" ");
}
printf("\n");
for(int i=0;i<SIZE;i++){
for(int j=0;j<SIZE;j++){
if(i==0){
if(j==0){
if(board[i][j]==1)
printf(" 1○─");
else if(board[i][j]==2)
printf(" 1●─");
else
printf(" 1┌─");
}
else if(j==SIZE-1){
if(board[i][j]==1){
printf("○");
printf("\n");
}
else if(board[i][j]==2){
printf("●");
printf("\n");
}
else{
printf("┐");
printf("\n");
}
}
else{
if(board[i][j]==1)
printf("○─");
else if(board[i][j]==2)
printf("●─");
else
printf("┬─");
}
}
else if(i>0&i<SIZE-1){
if(j==0){
if(i<9)
printf(" ");
if(board[i][j]==1)
printf("%d○─",i+1);
else if(board[i][j]==2)
printf("%d●─",i+1);
else
printf("%d├─",i+1);
}
else if(j==SIZE-1){
if(board[i][j]==1){
printf("○");
printf("\n");
}
else if(board[i][j]==2){
printf("●");
printf("\n");
}
else{
printf("┤");
printf("\n");
}
}
else{
if(board[i][j]==1)
printf("○─");
else if(board[i][j]==2)
printf("●─");
else
printf("┼─");
}
}
else{
if(j==0){
if(board[i][j]==1)
printf("%d○─",SIZE);
else if(board[i][j]==2)
printf("%d●─",SIZE);
else
printf("%d└─",SIZE);
}
else if(j==SIZE-1){
if(board[i][j]==1){
printf("○");
printf("\n");
}
else if(board[i][j]==2){
printf("●");
printf("\n");
}
else{
printf("┘");
printf("\n");
}
}
else{
if(board[i][j]==1)
printf("○─");
else if(board[i][j]==2)
printf("●─");
else
printf("┴─");
}
}
}
}
}
void put_white(int x,int y){
board[x-1][y-1]=2;
}
void put_black(int x,int y){
board[x-1][y-1]=1;
}
int get_chess(int x,int y){
return board[x-1][y-1];
}
int who_first(){
srand(time(NULL));
if(rand()%10<5) return 1;
else return 0;
}
int traversal_black(int x,int y){
int i,j,max;
int udsame=0,lrsame=0,ldsame=0,rdsame=0;
i=x;j=y;
while(RIGHT&&get_chess(--i,j)==1){
udsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(++i,j)==1){
udsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(i,--j)==1){
lrsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(i,++j)==1){
lrsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(--i,++j)==1){
ldsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(++i,--j)==1){
ldsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(--i,--j)==1){
rdsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(++i,++j)==1){
rdsame++;
}
max=udsame;
if(lrsame>max) max=lrsame;
if(ldsame>max) max=ldsame;
if(rdsame>max) max=rdsame;
return max;
}
int traversal_white(int x,int y){
int i,j,max;
int udsame=0,lrsame=0,ldsame=0,rdsame=0;
i=x;j=y;
while(RIGHT&&get_chess(--i,j)==2){
udsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(++i,j)==2){
udsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(i,--j)==2){
lrsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(i,++j)==2){
lrsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(--i,++j)==2){
ldsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(++i,--j)==2){
ldsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(--i,--j)==2){
rdsame++;
}
i=x;j=y;
while(RIGHT&&get_chess(++i,++j)==2){
rdsame++;
}
max=udsame;
if(lrsame>max) max=lrsame;
if(ldsame>max) max=ldsame;
if(rdsame>max) max=rdsame;
return max;
}
void menu(){
int input;
printf("*******************************************\n");
printf(" 五子棋\n");
printf(" 1 人机对战\n");
printf(" 2 双人游戏\n");
printf(" 3 退出游戏\n");
printf("*******************************************\n");
do{
printf("请输入选项 : ");
scanf("%d",&input);
getchar();
if(input!=1&&input!=2&&input!=3)
printf("输入错误请重新输入:\n");
}while(input!=1&&input!=2&&input!=3);
if(input==3) exit(0);
if(input==1) computer=1;
}
int *cpu_think(){
int best_pos[2]={10,10};
int *p=best_pos;
int score=0;
for(int i=1;i<=20;i++){
for(int j=1;j<=20;j++){
if(score<(9*traversal_white(i,j)+10*traversal_black(i,j))&&get_chess(i,j)==0){
score=9*traversal_white(i,j)+10*traversal_black(i,j);
*p=i;*(p+1)=j;
}
if(traversal_black(i,j)>3&&get_chess(i,j)==0){
*p=i;*(p+1)=j;
return p;
}
if(traversal_white(i,j)>3&&get_chess(i,j)==0){
*p=i;*(p+1)=j;
return p;
}
if(traversal_white(i,j)>2&&get_chess(i,j)==0){
*p=i;*(p+1)=j;
return p;
}
}
}
return p;
}
int main(){
int x,y;
int first=who_first();
menu();
system("clear");
print_board();
printf("输入(int)棋子坐标x y (以空格隔开)来放置棋子\n");
printf("输入两个0(以空格隔开)退出游戏\n");
if(first)
printf("黑棋先手\n");
else
printf("白棋先手\n");
while(1){
if(first){
do{
printf("输入黑棋坐标x y 以空格隔开 : ");
scanf("%d %d",&x,&y);
getchar();
if(x==0&&y==0) return 0;
if(x<1||x>SIZE||y<1||y>SIZE||get_chess(x,y)!=0)
printf("输入错误,重新输入:\n");
}while(x<1||x>SIZE||y<1||y>SIZE||get_chess(x,y)!=0);
printf("黑棋落子()%d,%d)",x,y);
put_black(x,y);
system("clear");
print_board();
if(traversal_black(x,y)>3){
puts("黑棋胜!");
return 1;
}
}
first=1;
if(!computer){
do{
printf("输入白棋坐标x y 以空格隔开: ");
scanf("%d %d",&x,&y);
getchar();
if(x==0&&y==0) return 0;
if(x<1||x>SIZE||y<1||y>SIZE||get_chess(x,y)!=0)
printf("输入错误,重新输入:\n");
}while(x<1||x>SIZE||y<1||y>SIZE||get_chess(x,y)!=0);
printf("白棋落子(%d,%d)\n",x,y);
}
if(computer){
x=*(cpu_think());
y=*(cpu_think()+1);
printf("电脑落子(%d,%d)\n",x,y);
}
put_white(x,y);
system("clear");
print_board();
if(traversal_white(x,y)>3){
puts("白棋胜 !");
return 1;
}
}
return 0;
}
|