C语言—————三子棋,步步分解

简介: C语言—————三子棋,步步分解

一.三子棋轮廓


游戏开始

打印目录,并让玩家选择是否玩游戏

当玩游戏我们需要一个棋盘

用二维数组存放下子位置,创建棋盘模样

玩家走,电脑走

判断输赢

游戏结束


实现目录

1.打印目录

2.玩家选择

3.创建一个二维数组

4.打印棋盘

5.玩家走

6.电脑走/玩家走

7.判断输赢

全部代码


二.根据轮廓来实现三子棋



附:下面的内容,皆以代码的形式直接展示,其代码为什么这么些附有注释。

1.打印目录

image.png

void mnue()
{
  printf("**********************\n");
  printf("*******  1. play  ****\n");
  printf("*******  0. exit  ****\n");
  printf("**********************\n");
}
...
mnue();
....

2.玩家选择

image.png

void mnue()
{
  printf("**********************\n");
  printf("*******  1. play  ****\n");
  printf("*******  0. exit  ****\n");
  printf("**********************\n");
}
int main()
{
  int input = 0;
  do//首先利用do while循环的先执行一道再判断进行打印目录并让玩家选择是否玩游戏
  {
    mnue();
    printf("是否玩游戏(1/0):>");
    scanf("%d",&input);//玩家选择1.玩游戏 0.退出游戏
    switch (input)
    {
    case 1:
      printf("猜数字游戏\n");
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("输入错误,请重新输入\n");
      break;
    }
  } while(input);
  return 0;
}

当我们选择1玩游戏时我们就会来到case1,并进到game()函数内

game函数:


3.创建一个二维数组

 image.png

分析:创建这些空间,即可以下子的空位置,并初始化成空格

//        test.c
#include"game.h"
void game()
{
char arr[ROW][COL] = {0};
//创建一个ROW行的,COL列的数组arr来存等一下 下子的位置
init(arr, ROW, COL);
...
//      game.h
#define ROW 3
#define COL 3   
//在头文件中用define定义常量这样就可以更方便的去修改这个棋盘的行,列
//如此时打印的棋盘大小是3*3的我们若想增大棋盘就可以直接在define处修改而不是
//一个一个的去修改行与列
void init(char arr[ROW][COL], int r, int c);//inti函数的声明,为了让inti函数可以在game.c中用
//         game.c
void init(char arr[ROW][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < r; i++)
  {
    for (j = 0; j < c; j++)
    {
      arr[i][j] = ' ';//现将数组内的所有内容,先置成空格
    }
  }
}

       此处用到了分源管理,创建一个自己的头文件(管理定义的常量,和函数的声明,和库函数所需的头文件),既然是头文件我们在使用时就要定义(#include"game.h")

4.打印棋盘

image.png

观察:可以发现棋盘由第一行和第二行循环打印而成(只不过有个别限制)的一组

分析:首先用循环打印第一行(第一行由将要下的子 %c 和 | 组成 ),并且限制不打印最后一个  ' | '

          其次用循环打印第二行( 第二行 由 --- 和 | 组成),并且限制不打印最后一个  ' | '

          最后把第一行与第二行看成一组循环打印,并且限制不打印最后一个第二行

//test.c
...
void game()
{
...
print(arr, ROW, COL);
...
//game.h
//打印棋盘
void print(char arr[ROW][COL],int r,int c);//声明
//game.c
void print(char arr[][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < r; i++)//打印时要小于行的大小
  {
    //此处分开一行一行打印是为了当我们改变行列时可以跟着改变打印                                                                                                    
    //的行列数
    for (j = 0; j < c; j++)   //打印时要小于列的大小
        {
      printf(" %c ", arr[i][j]);  //第一行由将要下的子 %c 和 | 组成 
      if (j < c - 1) //其中 | 在最后不用打印
        printf("|");
    }
    printf("\n");
    if (i < r - 1)    //第二行在最后不用打印
    {
      for (j = 0; j < c; j++)
      {
        printf("---")  ;  //第二行 有 --- 和 | 组成
        if (j < c - 1)  // | 在最后不用打印
          printf("|");
      }
      printf("\n");
    }
  }

开始下棋:玩家走一步,电脑走一步,不停的走直到一方胜利或则平局

5.玩家走

image.png

分析:当玩家输入坐标(因正常人并不知道数组下标所以要对应的-1)时在对应的坐标下入子('0') ,并打印玩家下子后的棋盘

//test.c
....
while(1)
{
play_move(arr, ROW, COL);
print(arr, ROW, COL);
...
game.h
...
//玩家走
void play_move(char arr[ROW][COL], int r, int c);
game.c
void play_move(char arr[][COL], int r, int c)
{
  int x = 0;
  int y = 0;
  while(1)
  {
    printf("玩家走:>");
    scanf("%d %d", &x, &y);
    printf("\n");
    if (x > 0 && x <= ROW && y > 0 && y <= COL)//首先判断玩家下的子是否满足行列范围
    {
            //x-1 ,y-1 因为一般人认为第一行第一列为1 1
      if (arr[x - 1][y - 1] == ' ')//当这个位置是空的就可以下子
      {
        arr[x - 1][y - 1] = 'O';//将这个位置下成 '0'
        break;
      }
      else
      {
        printf("该空已被占请重新输入\n");
      }
    }
    else
    {
      printf("错误输入,请重新输入\n");
    }
  }
}

6.电脑走

image.png

分析:要让电脑走,其实就是传入两个随机值并将产生坐标下入子'X'

//test.c
void game()
{
while(1)
{
    ...
    comput_move(arr, ROW, COL);
    print(arr, ROW, COL);
    ...
}
int main()
{
    srand((unsigned int)time(NULL));
....
game.h
//电脑走
void comput_move(char arr[ROW][COL], int r, int c);
game.c
void comput_move(char arr[][COL], int r, int c)
{
  printf("电脑走\n");
  while (1)
  {
    int x = rand() % r;//产生随机数模上行表示其大小范围是 0~r-1(2)
    int y = rand() % c;//同上列的范围是0~r-1(2)
    if (arr[x][y] == ' ')//不用想人一样加else,电脑若不对就再循环
    {
      arr[x][y] = 'X';
      break;
    }
  }
}

7.判断输赢

分析:

赢:

一行或者一列全部都为一种棋子时;对角线全部都为一种棋子时

平局:

先判断输赢,当输赢判断完发现并没有人赢时,再看这个二维数组的空间内是否还有空位置,若没了就代表平局,

谁都没赢:继续比赛

test.c
while()
{
    ...
    char re = 0;//储存返回的值
    ...
    re = is_win(arr, ROW, COL);//函数判断是否赢了,并返回一个值
    if (re != 'Q')//当返回的并不是继续游戏时
    {
      break;//跳出下子循环
    }
    ...
}
if(re == 'O')
  {
    printf("恭喜玩家赢了\n");
  }
  else if (re == 'B')
  {
    printf("平局\n");
  }
  else
  {
    printf("电脑都比你吊\n");
  }
game.h
char is_win(char arr[ROW][COL], int r, int c);
game.c
int is_full(char arr[ROW][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  int k = 0;
  for (i = 0; i < c; i++)
  {
    for (j = 0; j < r; j++)
    {
      if (arr[i][j] == ' ')//用循环判断数组内还有没有空格
      {
        k = 1;
        return k;//当有空格时将k置成1返回,代码有空格
      }
    }
  }
  return k;//当k没有变成1,就会返回初始化的k 0
}
char is_win(char arr[][COL], int r, int c)
{
  int j = 0;
  for (j = 0; j < r; j++)//用一行一行,一列一列的查
  {
    if (arr[j][0] == arr[j][1]&&arr[j][1] == arr[j][2] && arr[j][1] !=' ')
      //判断一行
            return arr[j][1];//当一行全部相等时返回其中的一个子
    if (arr[0][j] == arr[1][j] && arr[1][j] == arr[2][j] && arr[1][j] !=' ')
      //判断一列
            return arr[1][j];
  }
     //判断两对角线是否相等
  if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
    return arr[1][1];
  if(arr[1][2] == arr[1][1] && arr[3][1] == arr[1][1] && arr[1][1] != ' ')
    return arr[1][1];
    //判断还有没有空位置若没则平局
  int f = is_full(arr, ROW, COL);
  if (f == 0)//如果返回0 就代表没有空格了平局了
  {
    return 'B';
  }
  return 'Q';//当返回1时就代表还有空格可以继续游戏
}

全部代码

test.c

 #define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void game()
{
  while (getchar() != '\n')
  {
    ;
  }
  char re = 0;//声明存储是否赢了的标志
  char arr[ROW][COL] = {0};
  init(arr, ROW, COL);
  print(arr, ROW, COL);
  while (1)
  {
    play_move(arr, ROW, COL);
    print(arr, ROW, COL);
    /*printf("电脑走\n");*/
    Sleep(2000);
    re = is_win(arr, ROW, COL);
    if (re != 'Q')
    {
      break;
    }
    system("cls");
    comput_move(arr, ROW, COL);
    print(arr, ROW, COL);
    re = is_win(arr, ROW, COL);
    if (re != 'Q')
    {
      break;
    }
  }
  if(re == 'O')
  {
    printf("恭喜玩家赢了\n");
  }
  else if (re == 'B')
  {
    printf("平局\n");
  }
  else
  {
    printf("电脑都比你吊\n");
  }
}
void mnue()
{
  printf("**********************\n");
  printf("*******  1. play  ****\n");
  printf("*******  0. exit  ****\n");
  printf("**********************\n");
}
int main()
{
  srand((unsigned int)time(NULL));
  int input = 0;
  do
  {
    mnue();
    printf("是否玩游戏(1/0):>");
    scanf("%d",&input);
    switch (input)
    {
    case 1:
      printf("猜数字游戏\n");
      game();
      break;
    case 0:
      printf("退出游戏\n");
      break;
    default:
      printf("输入错误,请重新输入\n");
      break;
    }
  } while(input);
  return 0;
}

game.h:

#pragma once
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//棋盘初始化
void init(char arr[ROW][COL], int r, int c);
//玩家走
void play_move(char arr[ROW][COL], int r, int c);
//电脑走
void comput_move(char arr[ROW][COL], int r, int c);
//打印棋盘
void print(char arr[ROW][COL], int r, int c);
//判断输赢
char is_win(char arr[ROW][COL], int r, int c);

game.c:

 #define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int is_full(char arr[ROW][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  int k = 0;
  for (i = 0; i < c; i++)
  {
    for (j = 0; j < r; j++)
    {
      if (arr[i][j] == ' ')
      {
        k = 1;
        return k;
      }
    }
  }
  return k;
}
void init(char arr[ROW][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < r; i++)
  {
    for (j = 0; j < c; j++)
    {
      arr[i][j] = ' ';
    }
  }
}
void print(char arr[][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  for (i = 0; i < c; i++)
  {
    for (j = 0; j < c; j++)
    {
      printf(" %c ", arr[i][j]);
      if (j < c - 1)
        printf("|");
    }
    printf("\n");
    if (i < r - 1)
    {
      for (j = 0; j < c; j++)
      {
        printf("---");
        if (j < c - 1)
          printf("|");
      }
      printf("\n");
    }
  }
}
void play_move(char arr[][COL], int r, int c)
{
  int x = 0;
  int y = 0;
  while(1)
  {
    printf("玩家走:>");
    scanf("%d %d", &x, &y);
    printf("\n");
    if (x > 0 && x <= ROW && y > 0 && y <= COL)
    {
      if (arr[x - 1][y - 1] == ' ')
      {
        arr[x - 1][y - 1] = 'O';
        break;
      }
      else
      {
        printf("该空已被占请重新输入\n");
      }
    }
    else
    {
      printf("错误输入,请重新输入\n");
    }
  }
}
void comput_move(char arr[][COL], int r, int c)
{
  printf("电脑走\n");
  while (1)
  {
    int x = rand() % c;
    int y = rand() % r;
    if (arr[x][y] == ' ')
    {
      arr[x][y] = 'X';
      break;
    }
  }
}
char is_win(char arr[][COL], int r, int c)
{
  int i = 0;
  int j = 0;
  for (j = 0; j < r; j++)
  {
    if (arr[j][i] == arr[j][i + 1] && arr[j][i+1] == arr[j][i+2] && arr[j][i+1] != ' ')
      return arr[j][i+1];
    if (arr[i][j] == arr[i+1][j] && arr[i+1][j] == arr[i+2][j] && arr[i+1][j] != ' ')
      return arr[i+1][j];
  }
  if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ')
    return arr[1][1];
  if(arr[1][2] == arr[1][1] && arr[3][1] == arr[1][1] && arr[1][1] != ' ')
    return arr[1][1];
  int f = is_full(arr, ROW, COL);
  if (f == 0)
  {
    return 'B';
  }
  return 'Q';
}


相关文章
|
7月前
|
C语言
以c语言为基础实现的简易三子棋
以c语言为基础实现的简易三子棋
43 1
|
7月前
|
C语言
c语言简单三子棋
c语言简单三子棋
|
7月前
|
算法 C语言 C++
【C语言实战项目】三子棋游戏
【C语言实战项目】三子棋游戏
62 1
|
7月前
|
C语言
C语言之三子棋小游戏
C语言之三子棋小游戏
|
7月前
|
C语言
用c语言实现三子棋
用c语言实现三子棋
27 0
|
6月前
|
C语言
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
【海贼王编程冒险 - C语言海上篇】C语言如何实现简单的三子棋游戏?
32 1
|
7月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
82 1
|
7月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
93 1
|
7月前
|
编译器 C语言
【C语言入门小游戏】三子棋
【C语言入门小游戏】三子棋
55 0
【C语言入门小游戏】三子棋
|
7月前
|
C语言
【用C语言轻松搞定】三子棋(超详细教程)
【用C语言轻松搞定】三子棋(超详细教程)