C语言简单游戏编程入门之井字棋

游戏截图

在这里插入图片描述
在这里插入图片描述

源代码

person.h

//玩家对战 
void person()
{
	int i,j;
	initMap(map);
	//打印棋局 
	displayMap(map);
	//未分出胜负且棋局未落满子前无限循环 
	while(1)
	{
		//获取玩家下子位置 
		getXY(&i,&j);
		//玩家落子
		setPiece(map,i,j);
		//清屏 
		system("cls");
		//打印棋局 
		displayMap(map);
		//玩家落子后判断是否已经分出胜负
		if(isWin(map)==1)
		{
			//输出获胜方 
			displayWinner();
			break;
		}
		//是否棋局已满 
		else if(count==row*col)
		{
			printf("平局!\n");
			break;	
		} 
		//交替到对手回合
		exchangeTurn(); 
	}
}

computer.h

//局面价值 
int getSum(char map[][col])
{
	int sumO=0,sumX=0;
	int i,j;
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			if(map[i][j]=='O')
			{
				sumO+=score[i][j];
			}
			else if(map[i][j]=='X')
			{
				sumX+=score[i][j];
			}
		}
	}
	return sumX-sumO;
}

//思考
void think(char map[][col])
{
	int canWin=0;
	int i,j;
	int x=-1,y=-1;
	int sum;
	int maxSum=-20;
	count++;
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			if(map[i][j]==m)
			{
				map[i][j]='X';
				
				//能获胜,直接落子此处 
				if(isWin(map))
				{
					return;
				}
				//不能获胜,落子在分数最多的地方 
				else
				{
					map[i][j]='O';
					if(isWin(map))
					{
						map[i][j]='X';
						return;
					}
					map[i][j]='X';
					sum=getSum(map);
					if(sum>maxSum)
					{
						maxSum=sum;
						x=i;
						y=j;
					}
				}
				
				map[i][j]=m;	
			} 
		}
	}
	map[x][y]='X';	
}

void computer()
{
	int i,j;
	char computerType='X';
	initMap(map);
	//打印棋局 
	displayMap(map);
	//未分出胜负且棋局未落满子前无限循环 
	while(1)
	{
		//电脑落子 
		if(nowType==computerType)
		{
			printf("电脑落子:");
			think(map);
		}
		//玩家落子 
		else
		{
			//获取玩家下子位置 
			getXY(&i,&j);
			//玩家落子
			setPiece(map,i,j);
		}
	
		//清屏 
		system("cls");
		//打印棋局 
		displayMap(map);
		//玩家落子后判断是否已经分出胜负
		if(isWin(map)==1)
		{
			//输出获胜方 
			displayWinner();
			break;
		}
		//是否棋局已满 
		else if(count==row*col)
		{
			printf("平局!\n");
			break;	
		} 
		//交替到对手回合
		exchangeTurn(); 
	}
}

main.c

#include<stdio.h>
#include<stdlib.h>

//棋局
char map[3][3];
//行列
int row=3,col=3;
//棋子类型
char o='O',x='X',m=' ';
//当前棋子类型
char nowType='O'; 
//已落子数量
int count=0; 

//初始化棋局 
void initMap(char map[][col])
{
	int i,j;
	for(i=0;i<row;i++)
	{
		for(j=0;j<col;j++)
		{
			map[i][j]=m;
		}
	}
}

//打印当前棋局 
void displayMap(char map[][col])
{
	int i,j;
	printf("   ");
	for(i=0;i<col;i++)
	{
		printf("%d ",i);
	}
	printf("\n  ");
	for(i=0;i<2*col+1;i++)
	{
		printf("*");
	}
	printf("\n");
	for(i=0;i<row;i++)
	{
		printf("%d  ",i);
		for(j=0;j<col;j++)
		{
			printf("%c ",map[i][j]);
		}
		printf("\n  ");
		for(j=0;j<2*col+1;j++)
		{
			printf("*");
		}
		printf("\n");
	}
}

//获取用户输入
void getXY(int *i,int *j)
{
	while(1)
	{
		printf("落子方:%c\n",nowType);
		printf("落子位置(x,y)=");
		scanf("%d %d",i,j);
		if(*i<0||*i>=row||*j<0||*j>=col||map[*i][*j]!=m)
		{
			printf("输入不合法!\n");	
		}	
		else 
		{
			return;
		}	
	}
} 

//交替下子
void exchangeTurn()
{
	if(nowType==o)
	{
		nowType=x;
	}
	else
	{
		nowType=o;
	}
} 

//下子
void setPiece(char map[][col],int i,int j)
{
	map[i][j]=nowType;
	count++;
} 

//判断是否分出胜负,分别从横竖斜三个方向数数 
int isWin(char map[][col])
{
	int i,j;
	int flagR,flagC;
	for(i=0;i<row;i++)
	{
		flagR=0,flagC=0;
		for(j=0;j<col;j++)
		{
			if(map[i][j]==o)
			{
				flagR++;	
			}		
			else if(map[i][j]==x)
			{
				flagR--;
			}
			if(map[j][i]==o)
			{
				flagC++;
			}
			else if(map[j][i]==x)
			{
				flagC--;
			}
		}	
		if(flagR==col||flagC==col||flagR==(-col)||flagC==(-col))
		{
			return 1;
		}
	}	
	flagR=0,flagC=0;
	for(i=0,j=0;i<row&&j<col;i++,j++)
	{
		if(map[i][j]==o)
		{
			flagR++;
		}
		else if(map[i][j]==x)
		{
			flagR--;
		}
		if(map[i][col-j-1]==o)
		{
			flagC++;
		}
		else if(map[i][col-j-1]==x)
		{
			flagC--;
		}
	}
	if(flagR==col||flagC==col||flagR==(-col)||flagC==(-col))
	{
		return 1;
	}
	else 
	{
		return 0;
	}
} 

//输出胜方
void displayWinner()
{
	printf("%c方获得胜利!\n",nowType);	
} 

//给局面打分的基础表(站位分) 
int score[3][3]={
	{4,2,4},
	{2,8,2},
	{4,2,4}
};
//引入自定义头文件 
#include"person.h"
#include"computer.h"
 
int main()
{
	int gameType;
	printf("1.人机对战\n其他.玩家对战\n");
	scanf("%d",&gameType);
	if(gameType==1)
	{
		computer();
	}
	else
	{
		person();
	} 
	return 0;
}


代码解析

1、 其实棋类游戏设计最重要的就是模拟下棋的过程。
2、 我们知道井字棋是双方交替下子,一方执O,一方执X。
3、 比如O先下,玩家下完子后,我们判断一下此时他是否已经获胜(即是否出现横或竖或两斜线出现三子连珠的情况),没有获胜则判断是否已经将棋局下满子了,还是没有的话,轮到X的回合。再次执行此步骤。
4、 了解了过程就自然好设计了。因为棋局比较简单,我们用一个二维字符数组即可存储。落子位置用坐标(x,y),通过玩家输入即可进行模拟。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值