如何用c语言编写三子棋程序
目录
构造运行框架(主函数)
- 想要的效果:
出现一个界面让用户选自完游戏或者退出 - 用到do while循环和switch
- 将存放主函数的文件命名为test.c
#include<stdio.h>
#include<windows.h>
#include <time.h>
#include "game.h"
int main()
{
int select;
srand((unsigned int)time(NULL));
//一会用来产生随机数的,可暂时忽略
do
{
menu();
printf("请选择:");
scanf("%d",&select);
switch(select)
{
case 1: game();
break;
case 0: printf("已退出\n");
return 0;
default:printf("输入错误\n");
break;
}
}while(select);
return 0;
}
- 注意:
因为玩与不玩分别为1和0,对应条件真假,可直接放入whlie( select)进行判断
将各个功能写成函数
menu函数
用来输出游戏菜单,记得放在main函数之前防止主函数执行时menu并未声明。
void menu()
{
printf("************************\n");
printf("*** 1. play ***\n");
printf("*** 0. exit ***\n");
printf("************************\n");
}
game函数
game函数即为游戏运行的函数,即整个游戏的运行逻辑,放到test.c中。记得放在main函数之前防止main函数执行时game并未声明。
- 声明一个3*3的字符数组用来存储下棋内容
- rows和cols在后文的头文件中用define定义为的是以后方便更改,同时使函数功能不被限制
- 其中用到的函数后文逐个介绍
- 函数返回值为int类型为的是在判断输赢时方便结束函数
int game()
{
char table[rows][cols];
init(table, rows, cols);
while(1)
{
display(table,rows,cols);
PlayerMove(table);
switch(IsWin(table, rows, cols))
{
case 'x':
display(table,rows,cols);
printf("玩家赢\n");
return 0;
break;
case 'o':
display(table,rows,cols);
printf("电脑赢\n");
return 0;
break;
case 'k':
break;
case 'p':
display(table,rows,cols);
printf("平局\n");
return 0;
break;
}
ComputerMove(table);
switch(IsWin(table, rows, cols))
{
case 'x':
display(table,rows,cols);
printf("玩家赢\n");
return 0;
break;
case 'o':
display(table,rows,cols);
printf("电脑赢\n");
return 0;
break;
case 'k':
break;
case 'p':
display(table,rows,cols);
printf("平局\n");
return 0;
break;
}
}
}
创建一个game.c源文件和game.h头文件
game.c里面写game函数需要的子函数(用来实现游戏运行的每个功能)
game.h中用来声明game.c中的函数。
记得在两个原文建中引头文件。
- 头文件game.h内容如下
#ifndef __GAME_H__
#define __GAME_H__
#include<stdio.h>
#include<windows.h>
#include <time.h>
#define rows 3
#define cols 3
char IsWin(char table[rows][cols],int row, int col);
void PlayerMove(char table[rows][cols]);
void ComputerMove(char table[rows][cols]);
void init(char table[rows][cols],int row, int col);
void display(char table[rows][cols], int row, int col);
#endif
梳理game函数需要的功能(各函数)
- 棋盘(数组)的初始化——init函数
- 棋盘的展示——display函数
- 玩家下棋——PlayerMove函数
- 电脑下棋——ComputerMove函数
- 判断输赢——IsWin函数
init函数
为声明好的数组初始化,也是为游戏结束后为数组从新出使化
- 用到for循环,返回类型为空
void init(char table[rows][cols],int row, int col)
{
int i, j;
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
table[i][j]=' ';
}
}
}
display函数
用来展示棋盘,类似遍历二维数组。
- 返回类型为空
- 考虑遍历数组需要数组和数组的长度设计参数
- 不仅仅是遍历还要输出棋盘格
void display(char table[rows][cols], int row, int col)
{
int i;
for(i=0; i<row; i++)
{
printf(" %c | %c | %c \n",table[i][0],table[i][1],table[i][2]);
if(i<2)
{
printf("___ ___ ___\n");
}
}
printf("\n");
}
PlayerMove函数
接受用户玩家坐标(用户想要下棋的位置)存到数组中用于展示
- 参数需要数组
- 需判段用户输入坐标的合法性
void PlayerMove(char table[rows][cols])
{
int x,y;
printf("请输入坐标:");
while(1)
{
scanf("%d,%d",&x,&y);
if(x<=rows&&y<=cols)
{
if(table[x-1][y-1]==' ')
{
table[x-1][y-1]='x';
break;
}
else
{
printf("坐标已被占用\n");
}
}
else
{
printf("非法坐标,重新输入:");
}
}
}
ComputerMove函数
用户下棋后电脑下棋
- 用到rand( )函数,记得引time.h
- rand用来产生随机数,也就是说电脑下棋的位置是随机的,需电脑变聪明需做另外的设计,这里不做说明
- 不像玩家下棋需要判断合法性,我们这里直接生成合法坐标,但需判断是否被占用
- rand( )%rows是为产生的随机范围在[0,2]即合法范围
void ComputerMove(char table[rows][cols])
{
int x=0,y=0;
while(1)
{
x = rand()%rows;
y = rand()%cols;
if(table[x][y]==' ')
{
table[x][y]='o';
break;
}
}
}
IsWin函数
用来判断输赢,和平局情况
- game函数中判读输赢时用到switch语句,其case的值是字符,所以此函数返回值也应为char类型实现链式访问
- 判断赢分为横行竖行和斜,还有平局
- 玩家下棋后和电脑下棋后都需要判断
char IsWin(char table[rows][cols],int row, int col)
{
int i = 0,j = 0;
//hang
for(i=0; i<row; i++)
{
if(table[i][0]==table[i][1]&&table[i][0]==table[i][2])
return table[i][0];
}
//lie
for(i=0; i<col; i++)
{
if(table[0][i]==table[1][i]&&table[0][i]==table[2][i])
return table[0][i];
}
//xie
if((table[0][0]==table[1][1]&&table[0][0]==table[2][2])||
(table[0][2]==table[1][1]&&table[0][2]==table[2][0]))
{
return table[1][1];
}
for(i=0; i<row; i++)
{
for(j=0; j<col; j++)
{
if(table[i][j]==' ')
return 'k';
}
}
return 'p';
}