mirror of
https://github.com/hairrrrr/C-CrashCourse.git
synced 2026-02-03 10:43:15 +08:00
4-7
This commit is contained in:
33
code/practise/09 函数/01 判定素数/main.c
Normal file
33
code/practise/09 函数/01 判定素数/main.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include<stdio.h>
|
||||
#include<stdbool.h>
|
||||
|
||||
bool is_prime(int n) {
|
||||
|
||||
int divisor;
|
||||
|
||||
if (n <= 1)
|
||||
return false;
|
||||
|
||||
for (divisor = 2; divisor * divisor <= n; divisor++) {
|
||||
if (n % divisor == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
int n;
|
||||
|
||||
printf("Enter a number: ");
|
||||
scanf("%d", &n);
|
||||
|
||||
if (is_prime(n))
|
||||
printf("Prime\n");
|
||||
else
|
||||
printf("Not Prime\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
10
code/practise/09 函数/01 判定素数/readme.md
Normal file
10
code/practise/09 函数/01 判定素数/readme.md
Normal file
@@ -0,0 +1,10 @@
|
||||
#### 程序:判断素数
|
||||
|
||||
编写程序提示用户录入数,然后给出一条信息说明此数是否为素数。
|
||||
|
||||
```c
|
||||
Enter a number: 24
|
||||
Not prime
|
||||
```
|
||||
|
||||
把判断素数的实现写到另外一个函数中,此函数返回值为 true 就表示是素数,返回 false 表示不是素数。
|
||||
74
code/practise/10 程序结构/01 猜数/global_variable.c
Normal file
74
code/practise/10 程序结构/01 猜数/global_variable.c
Normal file
@@ -0,0 +1,74 @@
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<time.h>
|
||||
|
||||
#define MAX_NUMBER 100
|
||||
|
||||
int secret_number;// 要猜的数
|
||||
|
||||
void generate_secret_number();// 随机数生成
|
||||
void read_guesses(); // 猜的实现
|
||||
|
||||
int main(void) {
|
||||
|
||||
char command;
|
||||
|
||||
printf("Guess the secret number between 1 and 100.\n");
|
||||
|
||||
do {
|
||||
generate_secret_number();
|
||||
printf("A new number has been chosen.\n");
|
||||
read_guesses();
|
||||
printf("Play again?(Y/N)");
|
||||
scanf(" %c", &command);// 注意 %c 前的空格,这很重要
|
||||
printf("\n");
|
||||
} while (command == 'y' || command == 'Y');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 可以用这样的注释将函数的功能写在函数的定义的上方
|
||||
// 我个人比较喜欢将简单的注释写在函数原型处
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* generate_secret_number: Initilizes the random number generator using the
|
||||
* time of day.Randomly selects a number between
|
||||
* 1 and MAX_NUMBER and stores it in secret_number
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void generate_secret_number() {
|
||||
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
secret_number = rand() % MAX_NUMBER + 1;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*
|
||||
* read_guesses:Repeatedly reads user guesses and gives hints
|
||||
* When guess is right,prints the total number of
|
||||
* guesses and returns
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
void read_guesses() {
|
||||
|
||||
int guess, count = 0;
|
||||
|
||||
for (;;) {
|
||||
printf("Enter guess: ");
|
||||
scanf("%d", &guess);
|
||||
count++;
|
||||
if (guess > secret_number) {
|
||||
printf("Too high; try again\n");
|
||||
}
|
||||
else if (guess < secret_number) {
|
||||
printf("Too low; try again.\n");
|
||||
}
|
||||
else {
|
||||
printf("You won in %d guesses!\n\n", count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
59
code/practise/10 程序结构/01 猜数/no_global_variable.c
Normal file
59
code/practise/10 程序结构/01 猜数/no_global_variable.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<time.h>
|
||||
|
||||
#define MAX_NUMBER 100
|
||||
|
||||
int generate_secret_number();// Ëæ»úÊýÉú³É
|
||||
void read_guesses(int secret_number); // ²ÂµÄʵÏÖ
|
||||
|
||||
int main(void) {
|
||||
|
||||
char command;
|
||||
int secret_number;
|
||||
|
||||
printf("Guess the secret number between 1 and 100.\n");
|
||||
|
||||
do {
|
||||
secret_number = generate_secret_number();
|
||||
printf("A new number has been chosen.\n");
|
||||
read_guesses(secret_number);
|
||||
printf("Play again?(Y/N)");
|
||||
scanf(" %c", &command);
|
||||
printf("\n");
|
||||
} while (command == 'y' || command == 'Y');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int generate_secret_number() {
|
||||
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
int secret_number = rand() % MAX_NUMBER + 1;
|
||||
|
||||
return secret_number;
|
||||
}
|
||||
|
||||
void read_guesses(int secret_number) {
|
||||
|
||||
int guess, count = 0;
|
||||
|
||||
for (;;) {
|
||||
printf("Enter guess: ");
|
||||
scanf("%d", &guess);
|
||||
count++;
|
||||
if (guess > secret_number) {
|
||||
printf("Too high; try again\n");
|
||||
}
|
||||
else if (guess < secret_number) {
|
||||
printf("Too low; try again.\n");
|
||||
}
|
||||
else {
|
||||
printf("You won in %d guesses!\n\n", count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
code/practise/10 程序结构/01 猜数/readme.md
Normal file
19
code/practise/10 程序结构/01 猜数/readme.md
Normal file
@@ -0,0 +1,19 @@
|
||||
#### 程序:猜数
|
||||
|
||||
程序产生一个 1 ~ 100 的随机数,用户尝试用尽可能少的次数猜出这个数。程序运行如下:
|
||||
|
||||
```c
|
||||
Guess the secret number between 1 and 100.
|
||||
|
||||
A new number has been chosen.
|
||||
Enter guess:55
|
||||
Too low; try again.
|
||||
Enter guess:65
|
||||
Too high; try again.
|
||||
Enter guess: 60
|
||||
You won in 3 guesses!
|
||||
|
||||
Play again?(Y/N) n
|
||||
```
|
||||
|
||||
使用两种方法:使用全局变量/不使用全局变量
|
||||
209
code/practise/10 程序结构/02 手牌分类/main.c
Normal file
209
code/practise/10 程序结构/02 手牌分类/main.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 程序难点思路:
|
||||
* 1)为了判定手中的牌是否重复,我们需要一个布尔类型数组存储整副牌,初始化整个数组为 false。如果一张牌已经在我们手上,那么我们将数组对应的元素置为 true
|
||||
* 2)用两个分别数组来存储每个点数和花色的个数,这样方便我们后面判断牌的类型
|
||||
* 3)8 种牌的类型,我们可拆成 同花,顺子,4张,3张,对子(值为 0,1,2)这五种基础类型的组合。
|
||||
*
|
||||
* 程序结构:
|
||||
* 通过上面的分析,我们发现:这个程序需要 3 个数组和 5 个变量,如果都作为函数参数传参,显得有些笨。
|
||||
* 而且,前面我们说过,函数只能返回一个值,那如果要将函数分离, 5 种基础类型就得放进数组;或者使用指针,而指针我们没有学习,而且指针还是逃不开传参
|
||||
* 这样一分析,貌似使用全局变量是最好的做法了。对于初学者来说,这样可能确实是最好的。
|
||||
* 但是,使用大量的全局变量是很不好的习惯,我不能让自己去写这样的代码。我认为:宁可这道题不做,也不能有坏的代码风格去写!
|
||||
* 后面我们会学习自定义类型:结构体,它可能是这种问题最好的解决方法。
|
||||
*
|
||||
* 下面是这个问题的 4 种解决方法:
|
||||
* 1)应用全局变量
|
||||
* 2)应用指针作为函数参数
|
||||
* 3)将判断卡牌类型的函数与打印函数合并
|
||||
* 4)使用结构体
|
||||
*
|
||||
* 在这里,我坚持使用结构体来解决这类问题。全局变量大家只要知道概念即可,对于这道题来说,比起方法,可能设计程序的模块化思路更值得学习。
|
||||
* 即使使用结构体,程序的主要逻辑也不会变。如果你非要用全局变量写,那你可以改写一下。
|
||||
*/
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdbool.h>
|
||||
|
||||
#define RANK 13
|
||||
#define SUIT 4
|
||||
#define CARD 5
|
||||
|
||||
typedef struct CardType {
|
||||
bool flush; //同花
|
||||
bool straight; //顺子
|
||||
bool four; //四张
|
||||
bool three; //三张
|
||||
int pair; // 对子
|
||||
// 0 表示不是 1 表示 1个对子 2 表示两个对子
|
||||
bool cardInHand[SUIT][RANK]; // 判断此牌是否已在手中
|
||||
int numRank[RANK]; // 每个点数的个数
|
||||
int numSuit[SUIT]; // 每个花色的个数
|
||||
}CardType;
|
||||
|
||||
|
||||
void initCardType(CardType* card); // 初始化
|
||||
void readCard(CardType* card); // 读取输入
|
||||
void analyseCard(CardType* card); // 分析手牌
|
||||
void printResult(CardType* card); //打印结果
|
||||
|
||||
int main(void) {
|
||||
|
||||
CardType card;
|
||||
|
||||
for (; ;) {
|
||||
initCardType(&card);
|
||||
readCard(&card);
|
||||
analyseCard(&card);
|
||||
printResult(&card);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void initCardType(CardType* card) {
|
||||
|
||||
card->flush = false;
|
||||
card->straight = false;
|
||||
card->four = false;
|
||||
card->three = false;
|
||||
card->pair = 0;
|
||||
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < SUIT; i++) {
|
||||
card->numSuit[i] = 0;
|
||||
for (j = 0; j < RANK; j++) {
|
||||
card->cardInHand[i][j] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < RANK; i++) {
|
||||
card->numRank[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void readCard(CardType* card) {
|
||||
|
||||
int card_read = CARD, rank, suit;
|
||||
bool bad_card;
|
||||
char ch;
|
||||
|
||||
while (card_read) {
|
||||
|
||||
bad_card = false; // 不要忘记重置坏牌的标记
|
||||
|
||||
printf("Enter a card : ");
|
||||
|
||||
// 判断点数
|
||||
ch = getchar();
|
||||
switch (ch) {
|
||||
case '0': exit(0); break;
|
||||
case '2': rank = 0; break;
|
||||
case '3': rank = 1; break;
|
||||
case '4': rank = 2; break;
|
||||
case '5': rank = 3; break;
|
||||
case '6': rank = 4; break;
|
||||
case '7': rank = 5; break;
|
||||
case '8': rank = 6; break;
|
||||
case '9': rank = 7; break;
|
||||
case 't':case 'T': rank = 8; break;
|
||||
case 'j':case 'J': rank = 9; break;
|
||||
case 'q':case 'Q': rank = 10; break;
|
||||
case 'k':case 'K': rank = 11; break;
|
||||
case 'a':case 'A': rank = 12; break;
|
||||
default:bad_card = true; break;
|
||||
}
|
||||
|
||||
ch = getchar();
|
||||
switch (ch) {
|
||||
case 'c': case 'C': suit = 0; break;
|
||||
case 'd': case 'D': suit = 1; break;
|
||||
case 'h': case 'H': suit = 2; break;
|
||||
case 's': case 'S': suit = 3; break;
|
||||
default: bad_card = true; break;
|
||||
}
|
||||
|
||||
// !!! 精华 1
|
||||
// 检测输入是否多于两个字符
|
||||
while ((ch = getchar()) != '\n') {
|
||||
if (ch != ' ')
|
||||
bad_card = true;
|
||||
}
|
||||
|
||||
if (bad_card)
|
||||
printf("Bad card; ignored.\n");
|
||||
else if (card->cardInHand[suit][rank])
|
||||
printf("Duplicated card; ignored.\n");
|
||||
else {
|
||||
++card->numRank[rank];
|
||||
++card->numSuit[suit];
|
||||
card->cardInHand[suit][rank] = true;
|
||||
card_read--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void analyseCard(CardType* card) {
|
||||
|
||||
int i, count;
|
||||
|
||||
// 同花是五张牌相同花色
|
||||
for (i = 0; i < SUIT; i++) {
|
||||
if (card->numSuit[i] == 5)
|
||||
card->flush = true;
|
||||
}
|
||||
|
||||
// !!! 精华 2
|
||||
// 顺子是五张连续的牌,中间不能隔断
|
||||
|
||||
i = 0;
|
||||
// 找到数组种第一张存在的牌
|
||||
while (card->numRank[i] == 0)
|
||||
i++;
|
||||
count = 0;
|
||||
for (; i < RANK && card->numRank[i] != 0; i++) {
|
||||
count++;
|
||||
}
|
||||
// 顺子必须是五张
|
||||
if (count == CARD) {
|
||||
card->straight = true;
|
||||
return; // 顺子肯定不是对子
|
||||
}
|
||||
|
||||
for (i = 0; i < RANK; i++) {
|
||||
if (card->numRank[i] == 4)
|
||||
card->four = true;
|
||||
if (card->numRank[i] == 3)
|
||||
card->three = true;
|
||||
if (card->numRank[i] == 2)
|
||||
++card->pair;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void printResult(CardType* card) {
|
||||
|
||||
if (card->flush && card->straight)
|
||||
printf("Stright flush\n");
|
||||
else if (card->four)
|
||||
printf("Four of a kind\n");
|
||||
else if (card->three && card->pair == 1)
|
||||
printf("Full house\n");
|
||||
else if (card->flush)
|
||||
printf("flush\n");
|
||||
else if (card->straight)
|
||||
printf("straight\n");
|
||||
else if (card->three)
|
||||
printf("Three of a kind\n");
|
||||
else if (card->pair == 2)
|
||||
printf("Two pairs\n");
|
||||
else if (card->pair == 1)
|
||||
printf("pair\n");
|
||||
else
|
||||
printf("High card\n");
|
||||
|
||||
printf("\n\n");
|
||||
}
|
||||
56
code/practise/10 程序结构/02 手牌分类/readme.md
Normal file
56
code/practise/10 程序结构/02 手牌分类/readme.md
Normal file
@@ -0,0 +1,56 @@
|
||||
#### 程序:手牌分类
|
||||
|
||||
编写程序对手牌进行读取和分类。手中的每张牌都有花色(方块,梅花,红桃和黑桃)和等级(2,3,4,5,6,7,8,9,T,J,Q,K 和 A)。不允许使用王牌,并且假设 A 是最高等级的。一手 5 张牌,然后把手中的牌分为下列某一类(列出的顺序从好到坏)。
|
||||
|
||||
- 同花顺(顺序连续且同花色)
|
||||
- 四张(4 张牌等级相同)
|
||||
- 葫芦(3 张牌等级一样,另外2 张等级一样)
|
||||
- 同花(5 张牌同花色)
|
||||
- 顺子(5 张牌等级顺序连续)
|
||||
- 三张(3 张牌等级连续)
|
||||
- 两对
|
||||
- 一对(2 张牌等级一样)
|
||||
- 其他牌
|
||||
|
||||
如果一手牌可以分为两种或多种类别,程序将选择最好的一种。
|
||||
|
||||
为了便于输入,将牌的等级和花色简化如下:
|
||||
|
||||
- 等级: 2,3,4,5,6,7,8,9,T,J,Q,K ,A
|
||||
- 花色:c d h s
|
||||
|
||||
如果用户输入非法牌或者输入同一张牌两次,程序将此牌忽略掉,产生错误信息,然后要求输入另一张牌。如果输入为 0 而不是一张牌,就会导致程序终止。
|
||||
|
||||
与程序的会话如下:
|
||||
|
||||
```c
|
||||
Enter a card : 2s
|
||||
Enter a card : 5s
|
||||
Enter a card : 4s
|
||||
Enter a card : 3s
|
||||
Enter a card : 6s
|
||||
Straight flush
|
||||
|
||||
Enter a card : 8c
|
||||
Enter a card : as
|
||||
Enter a card : 8c
|
||||
Duplicated card; ignored.
|
||||
Enter a card : 7c
|
||||
Enter a card : ad
|
||||
Enter a card : 3h
|
||||
Pair
|
||||
|
||||
Enter a card : 6s
|
||||
Enter a card : d2
|
||||
Bad card; ignored.
|
||||
Enter a card : 2d
|
||||
Enter a card : 9c
|
||||
Enter a card : 4h
|
||||
Enter a card : ts
|
||||
High card
|
||||
|
||||
Enter a card: 0
|
||||
```
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user