C语言实现三子棋

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本篇为用C语言实现三子棋,主要时熟悉C语言的函数和循环,重点在功能实现的逻辑。

一、创建阶段

项目比较简单,我们在VS_CODE里面,在自己的项目文件夹下,创建SZQ_main.c文件,用于实现主体的功能和函数的实现,再定义一个SZQ_main.h文件,用于存放此项目所用到的所有头文件,以及函数的声明。

二、主要步骤

1.先把菜单打印出来

我们玩游戏一般是有个选择的菜单,可以选择玩和不玩。先确认是否进入游戏,选择1,进入;选择0,退出;选择其他数字,则显示输入错误。此处需要用到while循环和switch语句。
在这里插入图片描述
代码如下:

void menu(){
    printf("**************************************\n");
    printf("*************1,play  0,exit***********\n");
     printf("**************************************\n");
}
int main(){
    //srand((unsigned int )time(NULL)); //设置随机数的生成起点
    int input =0;
    do {
        menu();
        printf("请选择:");
        scanf("%d",&input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
        printf("输入错误");
            break;
        }

    }while (input);
    
    return 0;
}

2.主体框架搭建和实现

1,先把三子棋的板子先弄出来
用户选择1后开始游戏,这时我们就要把棋盘打印出来,这个棋盘由棋子和格子构成。这里的棋子,我们要定义一个二维数组,大家观察下面的棋盘,会发现初始化的棋盘没有棋子,其实,这里的棋子被初始化为空格。
在这里插入图片描述
代码如下
注意:这里我预先在SZQ_main.h里面给行和列进行了宏定义,方便以后进行修改,以及函数声明:

#ifndef _SZQ_MAIN_H_
#define _SZQ_MAIN_H_
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int  row,int  col);
void DisplayBoard(char board[ROW][COL],int  row,int  col);
void PlauerMove(char board[ROW][COL],int  row,int  col);
void ComputerMove(char board[ROW][COL],int  row,int  col);
char IsWin(char board[ROW][COL],int  row,int  col);
int  IsFull(char board[ROW][COL],int  row,int  col);
#endif

函数主体代码如下,先给棋盘初始化成空格,然后再打印出来:

void InitBoard(char board[ROW][COL],int  row,int  col){
    int i=0;
    int j=0;
    for(i=0;i<row;i++){
         for(j=0;j<col;j++){
            board[i][j]= ' ';
         }
    }
}
void DisplayBoard(char board[ROW][COL],int  row,int  col){
    int i=0;
    for(int i=0;i<row;i++){
      //  printf(" %c | %c | %c \n",board[i][0], board[i][1],board[i][2]);
      int j=0;
      for(j=0;j<col;j++){
        printf(" %c ",board[i][j]);
        if(j<col-1){
            printf("|");
        }
 }
        printf("\n");
      
        if(i<row-1){
            int j=0;
            for(j=0;j<col;j++){
                //printf("---|---|---\n");
            printf("---");
            if(j<col-1)
            printf("|");  
            }
          printf("\n");
        }
    }
}

2.玩家下棋和电脑下棋的实现
玩家手动输入所选的坐标,电脑自动选择位置。
在这里插入图片描述
关于玩家部分,我们根据用它关乎输入的坐标,由于我们的棋盘数组是从9开始的吗,所以,我们要在将棋盘打印出用户下棋子的情况,需要用户输入的坐标x和y都减去1。代码实现如下:

//玩家下棋
void PlayerMove(char board[ROW][COL],int  row,int  col){
    int x=0;
    int y=0;
    printf("玩家请下棋:");
   
    while (1)
    {
    printf("玩家请输入坐标:");
    scanf("%d %d",&x,&y); 
    //合法坐标
       if(x>=1 && x<=row && y>=1 && y <=col){
            if(board[x-1][y-1]==' '){
                board[x-1][y-1]='*';
                break;
            }
            else{
                printf("坐标已经被占用,不能下棋,请选择其他位置:");
            }
       } 
       else{
            printf("非法坐标!重新数输入:");
       }
    }
    




}

关于电脑端部分,我们电脑下的棋用‘#’显示。此处要用到rand()函数,rand()函数为电脑获取随机的一个大于0的整数,因为电脑选择的坐标范围是0~2,需要x=rand()%3来实现,因为任意一个整数对3取余数,就只有0,1,2的可能。为保证每次选择的坐标不同,需要在主函数添加srand((unsigned int)time(NULL));这个代码是时间戳,保证每个时刻获取的坐标不同。这里需要<stdlib.h>以及<time.h>头文件。当然这样的好处是方便,但是不够人心性化,我们也可以采用堵玩家下棋的方式来模拟电脑下棋,这个需要自己去实现。
代码实现如下:

void ComputerMove(char board[ROW][COL],int  row,int  col){
    printf("电脑下棋->\n");
    int x=0;
    int y=0;
    while (1)
    {
        x=rand()%row;//0-2
        y=rand()%col;//0-2
        if(board[x][y]==' '){
        board[x][y]='#';
        break;
    }/* code */
    }
    
 
}

3.判断胜负
我们需要判断出到底是谁赢了,或者是不是平局了。若有一方一行,一列,一条对角线连成一条线,则此方胜利,若棋盘已满,但没有胜负,则平局。
关于以下函数的返回值,玩家赢,返回‘*’;电脑赢,返回‘#’;平局,返回‘Q’;否则,游戏继续,返回‘C’。

在这里插入图片描述
代码实现如下:

char IsWin(char board[ROW][COL],int  row,int  col){
    //hang
    int i=0;
    for(i=0;i<row;i++){
            if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][1]!=' '){
               return board[i][1];
            }
    }
    //lie
    int j=0;
      for(j=0;i<col;j++){
            if(board[0][j]==board[1][j] &&board[1][j]==board[2][j]&&board[1][j]!=' '){
               return board[1][j];
            }
    }
    //duijiaoxian
    if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' '){
        return board[0][0];
    }
    if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' '){
        return board[0][2];
    }
    //
   if(IsFull(board,row,col)){
        return 'Q';
   }
   return 'C';
}

此处我们添加一个判断棋盘是否已满的函数IsFull();

//满了返回1,否为0
int  IsFull(char board[ROW][COL],int  row,int  col){
    int i;
    for(i=0;i<row;i++){
        for(int j=0;j<col;j++){
            if(board[i][j]==' ')
           {return 0;} 
           
        }
    }
    return 1;
}

完整代码如下:

SZQ_main.c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include"SZQ_main.h"


//玩家下棋
void PlayerMove(char board[ROW][COL],int  row,int  col){
    int x=0;
    int y=0;
    printf("玩家请下棋:");
   
    while (1)
    {
    printf("玩家请输入坐标:");
    scanf("%d %d",&x,&y); 
    //合法坐标
       if(x>=1 && x<=row && y>=1 && y <=col){
            if(board[x-1][y-1]==' '){
                board[x-1][y-1]='*';
                break;
            }
            else{
                printf("坐标已经被占用,不能下棋,请选择其他位置:");
            }
       } 
       else{
            printf("非法坐标!重新数输入:");
       }
    }
    




}

void ComputerMove(char board[ROW][COL],int  row,int  col){
    printf("电脑下棋->\n");
    int x=0;
    int y=0;
    while (1)
    {
        x=rand()%row;//0-2
        y=rand()%col;//0-2
        if(board[x][y]==' '){
        board[x][y]='#';
        break;
    }/* code */
    }
    
 
}

void InitBoard(char board[ROW][COL],int  row,int  col){
    int i=0;
    int j=0;
    for(i=0;i<row;i++){
         for(j=0;j<col;j++){
            board[i][j]= ' ';
         }
    }
}
void DisplayBoard(char board[ROW][COL],int  row,int  col){
    int i=0;
    for(int i=0;i<row;i++){
      //  printf(" %c | %c | %c \n",board[i][0], board[i][1],board[i][2]);
      int j=0;
      for(j=0;j<col;j++){
        printf(" %c ",board[i][j]);
        if(j<col-1){
            printf("|");
        }
 }
        printf("\n");
      
        if(i<row-1){
            int j=0;
            for(j=0;j<col;j++){
                //printf("---|---|---\n");
            printf("---");
            if(j<col-1)
            printf("|");  
            }
          printf("\n");
        }
    }
}

char IsWin(char board[ROW][COL],int  row,int  col){
    //hang
    int i=0;
    for(i=0;i<row;i++){
            if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][1]!=' '){
               return board[i][1];
            }
    }
    //lie
    int j=0;
      for(j=0;i<col;j++){
            if(board[0][j]==board[1][j] &&board[1][j]==board[2][j]&&board[1][j]!=' '){
               return board[1][j];
            }
    }
    //duijiaoxian
    if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' '){
        return board[0][0];
    }
    if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]!=' '){
        return board[0][2];
    }
    //
   if(IsFull(board,row,col)){
        return 'Q';
   }
   return 'C';
}
//满了返回1,否为0
int  IsFull(char board[ROW][COL],int  row,int  col){
    int i;
    for(i=0;i<row;i++){
        for(int j=0;j<col;j++){
            if(board[i][j]==' ')
           {return 0;} 
           
        }
    }
    return 1;
}

void game(){
    char ret =0;
    char board[ROW][COL]={0};
    //初始化棋盘函数
    InitBoard(board,ROW,COL);
    DisplayBoard(board,ROW,COL); 
    //玩家下棋
    while (1)
    {
       PlayerMove(board,ROW,COL);  
       ret=IsWin(board,ROW,COL);
       if(ret !='C'){
        break;
       }
        DisplayBoard(board,ROW,COL); 
        //判断是否赢了
        ComputerMove(board,ROW,COL);
         ret=IsWin(board,ROW,COL);
         if(ret !='C'){
        break;
       }
        DisplayBoard(board,ROW,COL); 
    }
    if(ret == '*'){
        printf("玩家赢了!\n");
    }
    else if(ret == '#'){
         printf("电脑赢了!\n");
    }
    else {
         printf("平局!\n");
    }
     DisplayBoard(board,ROW,COL); 
}

void menu(){
    printf("**************************************\n");
    printf("*************1,play  0,exit***********\n");
     printf("**************************************\n");
}
int main(){
    srand((unsigned int )time(NULL)); //设置随机数的生成起点
    int input =0;
    do {
        menu();
        printf("请选择:");
        scanf("%d",&input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
        printf("输入错误");
            break;
        }

    }while (input);
    
    return 0;
}
SZQ_main.h


```c
在这里插入代码#ifndef _SZQ_MAIN_H_
#define _SZQ_MAIN_H_
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL],int  row,int  col);
void DisplayBoard(char board[ROW][COL],int  row,int  col);
void PlauerMove(char board[ROW][COL],int  row,int  col);
void ComputerMove(char board[ROW][COL],int  row,int  col);
char IsWin(char board[ROW][COL],int  row,int  col);
int  IsFull(char board[ROW][COL],int  row,int  col);
#endif

# 总结
关于电脑下棋部分还可以自己多家修改,使其更加智能。这个项目主要是锻炼大家基本的函数调用,以及对数组的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值