Files
project1/第03课-嵌套循环与图形打印/编程题-教师版.md

661 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第6课编程题教师版
## 本课知识点覆盖表
| 核心知识点 | GESP等级 | 对应课堂题 |
|---|---|---|
| 外层控制行、内层控制列、实心矩形 | 二级必考 | 课堂1 |
| 行列关系、左下与右下三角形 | 二级必考 | 课堂2 |
| 空格数与星号数、等腰三角形与菱形 | 二级必考 | 课堂3 |
| 双层循环的非图形应用、行列组合 | 二级 | 课堂4 |
## 一、课堂练习4题
### 课堂1实心与空心矩形【适中】
**题目描述:** 输入行数 `n`、列数 `m` 和模式 `type`。当 `type=1` 时打印实心矩形;当 `type=2` 时打印空心矩形。
**输入格式:** 依次输入行数、列数和图形模式。
**输出格式:** 用星号打印指定矩形。
**数据范围:** `1≤n,m≤30``type` 为 1 或 2。
**输入样例:**
```text
3 5 2
```
**输出样例:**
```text
*****
* *
*****
```
**解题思路:** 双层循环枚举行列。实心模式总输出星号;空心模式只在首尾行或首尾列输出星号。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n, m, type;
cin >> n >> m >> type;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (type == 1 || i == 1 || i == n || j == 1 || j == m)
cout << "*";
else
cout << " ";
}
cout << "\n";
}
return 0;
}
```
**易错提醒:** 每打印完一行才换行;`n=1``m=1` 时所有位置都在边界上。
### 课堂2四种直角三角形【适中】
**题目描述:** 输入 `n` 和类型 `type`,打印边长为 `n` 的直角三角形1 左下、2 右下、3 左上、4 右上。
**输入格式:** 输入三角形边长和图形类型。
**输出格式:** 指定方向的星号三角形。
**数据范围:** `1≤n≤30``1≤type≤4`
**输入样例:**
```text
4 2
```
**输出样例:**
```text
*
**
***
****
```
**解题思路:**`i` 行星号数量为 `i``n-i+1`;右对齐时先输出相应数量空格。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n, type;
cin >> n >> type;
for (int i = 1; i <= n; i++) {
int stars = (type == 1 || type == 2) ? i : n - i + 1;
int spaces = (type == 2 || type == 4) ? n - stars : 0;
for (int j = 1; j <= spaces; j++) cout << " ";
for (int j = 1; j <= stars; j++) cout << "*";
cout << "\n";
}
return 0;
}
```
**易错提醒:** 右对齐不是改变星号数量,而是在星号前补空格。
### 课堂3等腰三角形与菱形【适中】
**题目描述:** 输入 `n` 和模式 `type`。模式 1 打印高为 `n` 的实心等腰三角形;模式 2 打印上下高度均为 `n`、中间行不重复的菱形。
**输入格式:** 输入图形高度和图形模式。
**输出格式:** 指定图形。
**数据范围:** `1≤n≤20`
**输入样例:**
```text
3 2
```
**输出样例:**
```text
*
***
*****
***
*
```
**解题思路:** 上半部分第 `i` 行有 `n-i` 个空格和 `2i-1` 个星号;菱形下半部分按相反规律输出。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
void printRow(int spaces, int stars) {
for (int j = 0; j < spaces; j++) cout << " ";
for (int j = 0; j < stars; j++) cout << "*";
cout << "\n";
}
int main() {
int n, type;
cin >> n >> type;
for (int i = 1; i <= n; i++) printRow(n - i, 2 * i - 1);
if (type == 2) {
for (int i = n - 1; i >= 1; i--) printRow(n - i, 2 * i - 1);
}
return 0;
}
```
**易错提醒:** 菱形下半部分从 `n-1` 开始,避免中间最长行重复。
### 课堂4九九乘法表【适中】
**题目描述:** 输入 `n`,打印 `1n` 的下三角乘法表。第 `i` 行输出 `1×i``i×i`
**输入格式:** 输入乘法表的最大因数。
**输出格式:** 下三角乘法表,每项格式为 `j*i=积`,项之间一个空格。
**数据范围:** `1≤n≤9`
**输入样例:**
```text
3
```
**输出样例:**
```text
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
```
**解题思路:** 外层 `i` 控制行和第二个因数,内层 `j` 从 1 走到 `i`
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
if (j > 1) cout << " ";
cout << j << "*" << i << "=" << j * i;
}
cout << "\n";
}
return 0;
}
```
**易错提醒:** 内层上界是当前行号 `i`,不是固定的 `n`
## 二、课后作业3题
### 课后1实心正方形【简单】
**题目描述:** 输入 `n`,打印 `n×n` 的星号正方形。
**输入格式:** 输入正方形的边长。
**输出格式:** 实心正方形。
**数据范围:** `1≤n≤20`
**输入样例:**
```text
3
```
**输出样例:**
```text
***
***
***
```
**解题思路:** 外层循环 `n` 行,内层每行输出 `n` 个星号。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) cout << "*";
cout << "\n";
}
return 0;
}
```
**易错提醒:** 换行语句应放在内层循环结束之后。
### 课后2左下数字三角形【简单】
**题目描述:** 输入 `n`,第 `i` 行输出 `i` 个数字 `i`
**输入格式:** 输入数字三角形的行数。
**输出格式:** 数字三角形。
**数据范围:** `1≤n≤9`
**输入样例:**
```text
4
```
**输出样例:**
```text
1
22
333
4444
```
**解题思路:** 外层行号决定输出数字,也决定内层循环次数。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) cout << i;
cout << "\n";
}
return 0;
}
```
**易错提醒:** 输出的是行号 `i`,不是列号 `j`
### 课后3棋盘格【简单】
**题目描述:** 输入 `n``m`,打印棋盘格;行列编号之和为偶数输出 `#`,否则输出 `.`
**输入格式:** 输入棋盘格的行数和列数。
**输出格式:** `n``m` 列棋盘格。
**数据范围:** `1≤n,m≤30`
**输入样例:**
```text
3 4
```
**输出样例:**
```text
#.#.
.#.#
#.#.
```
**解题思路:** 双层循环枚举位置,根据 `(i+j)%2` 决定字符。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++)
cout << ((i + j) % 2 == 0 ? '#' : '.');
cout << "\n";
}
return 0;
}
```
**易错提醒:** 行列从 1 开始时,左上角的和为 2应输出 `#`
## 三、扩展练习7题
### 扩展1坐标表【基础综合】
**题目描述:** 输入 `n m`,按行输出所有坐标 `(i,j)`
**输入格式:** 输入坐标表的行数和列数。
**输出格式:** 每行输出一行坐标,坐标之间一个空格。
**数据范围:** `1≤n,m≤10`
**输入样例:**
```text
2 2
```
**输出样例:**
```text
(1,1) (1,2)
(2,1) (2,2)
```
**解题思路:** 外层决定第一坐标,内层决定第二坐标。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (j > 1) cout << " ";
cout << "(" << i << "," << j << ")";
}
cout << "\n";
}
return 0;
}
```
**易错提醒:** 同一行坐标之间输出空格,行末不必输出多余空格。
### 扩展2回文数字三角形【中等】
**题目描述:** 输入 `n`,第 `i` 行依次输出 `1i1`
**输入格式:** 输入回文数字三角形的行数。
**输出格式:** 回文数字三角形。
**数据范围:** `1≤n≤9`
**输入样例:**
```text
4
```
**输出样例:**
```text
1
121
12321
1234321
```
**解题思路:** 每行使用两个内层循环:第一个递增到 `i`,第二个从 `i-1` 递减到 1。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) cout << j;
for (int j = i - 1; j >= 1; j--) cout << j;
cout << "\n";
}
return 0;
}
```
**易错提醒:** 下降部分从 `i-1` 开始,避免中间数字重复。
### 扩展3空心直角三角形【中等】
**题目描述:** 输入 `n`,打印左下空心直角三角形。
**输入格式:** 输入空心直角三角形的边长。
**输出格式:** 指定图形。
**数据范围:** `2≤n≤30`
**输入样例:**
```text
5
```
**输出样例:**
```text
*
**
* *
* *
*****
```
**解题思路:**`i` 行有 `i` 个位置;首列、斜边 `j=i`、底边 `i=n` 输出星号。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
if (j == 1 || j == i || i == n) cout << "*";
else cout << " ";
}
cout << "\n";
}
return 0;
}
```
**易错提醒:** 第二行两个位置都属于边界,所以会输出两个星号。
### 扩展4字母方阵【中等】
**题目描述:** 输入 `n`,第 `i` 行第 `j` 列输出从 `A` 开始向后平移 `i+j-2` 位的字母,超过 `Z` 循环。
**输入格式:** 输入字母方阵的边长。
**输出格式:** `n×n` 字母方阵。
**数据范围:** `1≤n≤20`
**输入样例:**
```text
3
```
**输出样例:**
```text
ABC
BCD
CDE
```
**解题思路:** 用行列共同决定平移量,字符公式为 `'A'+(i+j-2)%26`
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
cout << (char)('A' + (i + j - 2) % 26);
cout << "\n";
}
return 0;
}
```
**易错提醒:** ASCII 平移后要转换为字符;取模保证不会越过 `Z`
### 扩展5X形图案【中等】
**题目描述:** 输入奇数 `n`,打印 `n×n` 方阵,两条对角线输出 `*`,其他位置输出 `.`
**输入格式:** 输入一个奇数,表示方阵的边长。
**输出格式:** X 形图案。
**数据范围:** `1≤n≤31``n` 为奇数。
**输入样例:**
```text
5
```
**输出样例:**
```text
*...*
.*.*.
..*..
.*.*.
*...*
```
**解题思路:** 主对角线满足 `i=j`,副对角线满足 `i+j=n+1`
**参考代码:**
```cpp
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j || i + j == n + 1) cout << "*";
else cout << ".";
}
cout << "\n";
}
return 0;
}
```
**易错提醒:** 副对角线条件使用 `n+1`,因为行列编号从 1 开始。
### 扩展6空心菱形【略难】
**题目描述:** 输入 `n`,打印总高度为 `2n-1` 的空心菱形。
**输入格式:** 输入菱形上半部分的高度。
**输出格式:** 空心菱形。
**数据范围:** `1≤n≤20`
**输入样例:**
```text
3
```
**输出样例:**
```text
*
* *
* *
* *
*
```
**解题思路:** 把每一行映射为到中间行的层数 `level`;输出前导空格、左边星号,宽度大于 1 时再输出内部空格和右边星号。
**参考代码:**
```cpp
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int n;
cin >> n;
for (int row = 1; row <= 2 * n - 1; row++) {
int level = n - abs(n - row);
int outer = n - level;
int inner = 2 * level - 3;
for (int j = 0; j < outer; j++) cout << " ";
cout << "*";
if (inner >= 0) {
for (int j = 0; j < inner; j++) cout << " ";
cout << "*";
}
cout << "\n";
}
return 0;
}
```
**易错提醒:** 顶点和底点只有一个星号,此时不能输出第二个星号。
### 扩展7组合沙漏【略难】
**题目描述:** 输入 `n`,打印由星号组成的实心沙漏。第一行有 `2n-1` 个星号,逐行减少两个到 1再逐行增加两个中间行只输出一次。
**输入格式:** 输入沙漏上半部分的高度。
**输出格式:** 实心沙漏。
**数据范围:** `1≤n≤20`
**输入样例:**
```text
3
```
**输出样例:**
```text
*****
***
*
***
*****
```
**解题思路:** 上半部分第 `i` 行输出 `i-1` 个空格和 `2(n-i)+1` 个星号;下半部分反向恢复。
**参考代码:**
```cpp
#include <iostream>
using namespace std;
void printRow(int spaces, int stars) {
for (int j = 0; j < spaces; j++) cout << " ";
for (int j = 0; j < stars; j++) cout << "*";
cout << "\n";
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++)
printRow(i - 1, 2 * (n - i) + 1);
for (int i = n - 1; i >= 1; i--)
printRow(i - 1, 2 * (n - i) + 1);
return 0;
}
```
**易错提醒:** 下半部分从 `n-1` 开始,避免最窄的中间行重复。