Merge branch 'master' into master

This commit is contained in:
camera-2018
2024-01-26 22:04:30 +08:00
committed by GitHub
415 changed files with 15849 additions and 8572 deletions

3
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,3 @@
本次更新的内容主要为...
欢迎前来学习

View File

@@ -7,22 +7,25 @@ on:
jobs:
build:
if: github.repository == 'camera-2018/hdu-cs-wiki'
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@master
uses: actions/checkout@v3
- name: install dependencies
run: |
sudo pip install coscmd
sudo pip install tccli
npm i
- name: install doc dependencies
run: sudo npm i
- name: build
run: |
npm run docs:build
- name: install coscmd and tccli
run: |
sudo pip3 install coscmd
sudo pip3 install tccli
- name: confirgure coscmd and tccli
env:
SECRET_ID: ${{ secrets.TCLOUD_API_ID }}
@@ -30,7 +33,7 @@ jobs:
BUCKET: hdu-cs-wiki-1307923872
REGION: ap-shanghai
run: |
coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION -m 30 -p 10
coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION -m 10 -p 5
tccli configure set secretId $SECRET_ID
tccli configure set secretKey $SECRET_KEY
tccli configure set region $REGION

42
.github/workflows/link-pr.yaml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: links when pr
on:
pull_request:
branches: [ master ]
paths:
- '**.md'
- '.lycheeignore'
jobs:
linkChecker:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: install doc dependencies
run: sudo npm i
- name: build
run: |
npm run docs:build
- name: Link Checker
uses: lycheeverse/lychee-action@v1.8.0
with:
fail: true
# For parameter description, see https://github.com/lycheeverse/lychee#commandline-parameters
# -E, --exclude-all-private Exclude all private IPs from checking.
# -i, --insecure Proceed for server connections considered insecure (invalid TLS)
# -n, --no-progress Do not show progress bar.
# -t, --timeout <timeout> Website timeout in seconds from connect to response finished [default:20]
# --max-concurrency <max-concurrency> Maximum number of concurrent network requests [default: 128]
# -a --accept <accept> Comma-separated list of accepted status codes for valid links
# --max-retries <MAX_RETRIES> Maximum number of retries per request
# -r, --retry-wait-time <RETRY_WAIT_TIME> Minimum wait time in seconds between retries of failed requests
# -u, --user-agent <USER_AGENT> User agent
# *.md all markdown files in the root directory
args: -E -i -n -t 45 -r 3 --max-retries 5 --max-concurrency 64 -a 401,403 -u "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" -- '.vitepress/dist' '*.md'
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

49
.github/workflows/link-schedule.yaml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: links schedule
on:
# repository_dispatch:
workflow_dispatch:
schedule:
- cron: "0 0 */3 * *"
permissions:
issues: write
jobs:
linkChecker:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: install doc dependencies
run: sudo npm i
- name: build
run: |
npm run docs:build
- name: Link Checker
uses: lycheeverse/lychee-action@v1.8.0
with:
# For parameter description, see https://github.com/lycheeverse/lychee#commandline-parameters
# -E, --exclude-all-private Exclude all private IPs from checking.
# -i, --insecure Proceed for server connections considered insecure (invalid TLS)
# -n, --no-progress Do not show progress bar.
# -t, --timeout <timeout> Website timeout in seconds from connect to response finished [default:20]
# --max-concurrency <max-concurrency> Maximum number of concurrent network requests [default: 128]
# -a --accept <accept> Comma-separated list of accepted status codes for valid links
# --max-retries <MAX_RETRIES> Maximum number of retries per request
# -r, --retry-wait-time <RETRY_WAIT_TIME> Minimum wait time in seconds between retries of failed requests
# -u, --user-agent <USER_AGENT> User agent
# *.md all markdown files in the root directory
args: -E -i -n -t 45 -r 3 --max-retries 5 --max-concurrency 64 -a 401,403 -u "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" -- '.vitepress/dist' '*.md'
output: out.md
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Create Issue From File
uses: peter-evans/create-issue-from-file@v4
with:
title: Broken Link Detected
content-filepath: out.md
assignees: camera-2018

50
.github/workflows/subscribe.yaml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Subscribe to updates
on:
pull_request:
types:
- closed
branches:
- 'master'
paths:
- '**.md'
jobs:
subscribe:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
- name: Changed Files Exporter
id: changed-files
uses: umani/changed-files@v4.0.0
with:
repo-token: ${{ github.token }}
pattern: '^.*\.(md|markdown)$'
- name: Get PR labels
id: pr-labels
uses: joerick/pr-labels-action@v1.0.8
- name: Post Data
id: post-data
uses: octokit/request-action@v2.x
with:
route: POST https://np4l5e.laf.run/pr
repo: ${{github.event.repository.full_name}}
title: ${{ github.event.pull_request.title }}
work_branch: ${{ steps.branch.outputs.work_branch }}
base_branch: ${{ steps.branch.outputs.base_branch }}
id: ${{ github.event.pull_request.number }}
labels: ${{ steps.pr-labels.outputs.labels }}
files_updated: ${{ steps.changed-files.outputs.files_updated }}
files_created: ${{ steps.changed-files.outputs.files_created }}
files_deleted: ${{ steps.changed-files.outputs.files_deleted }}
source_url: ${{ github.event.pull_request.html_url }}
content: |
|
${{ github.event.pull_request.body }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@ node_modules
dist
cache
.temp
.vitepress/dist

9
.lycheeignore Normal file
View File

@@ -0,0 +1,9 @@
hdu-cs-wiki/edit
file://
https://adworld.xctf.org.cn/challenges/list
https://e5c78mnhgz.feishu.cn/docx/doxcnxBONvnxSLi0MfaNZWvrcSb
https://datawhale.feishu.cn/docs/doccn0AOicI3LJ8RwhY0cuDPSOc#
https://message.hdu-cs.wiki/
https://adworld.xctf.org.cn/
http://sequence-gallery.chal.crewc.tf:8080/
https://www.csie.ntu.edu.tw/~b97053/paper/Rendle2010FM.pdf

View File

@@ -0,0 +1,65 @@
<script setup>
import confetti from 'canvas-confetti'
import { watch } from 'vue'
const props = defineProps(
{
passed: {
type: Boolean,
required: true,
},
},
['passed'],
)
function congrats() {
const defaults = {
colors: [
'#5D8C7B',
'#F2D091',
'#F2A679',
'#D9695F',
'#8C4646',
],
shapes: ['square'],
ticks: 500,
}
confetti({
...defaults,
particleCount: 80,
spread: 100,
origin: { y: 0 },
})
setTimeout(() => {
confetti({
...defaults,
particleCount: 50,
angle: 60,
spread: 80,
origin: { x: 0 },
})
}, 250)
setTimeout(() => {
confetti({
...defaults,
particleCount: 50,
angle: 120,
spread: 80,
origin: { x: 1 },
})
}, 400)
}
watch(
() => props.passed,
(v) => {
if (v)
setTimeout(congrats, 300)
},
{ flush: 'post' },
)
</script>
<template>
<div />
</template>

View File

@@ -0,0 +1,111 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { withBase } from 'vitepress'
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import { useLangs } from 'vitepress/dist/client/theme-default/composables/langs'
import Sweep from './sweep.vue';
const { site, theme } = useData()
const { localeLinks } = useLangs({ removeCurrent: false })
const root = ref('/')
onMounted(() => {
const path = window.location.pathname
.replace(site.value.base, '')
.replace(/(^.*?\/).*$/, '/$1')
if (localeLinks.value.length) {
root.value =
localeLinks.value.find(({ link }) => link.startsWith(path))?.link ||
localeLinks.value[0].link
}
})
</script>
<template>
<div class="NotFound">
<p class="code">{{ theme.notFound?.code ?? '404' }}</p>
<h1 class="title">{{ theme.notFound?.title ?? 'PAGE NOT FOUND' }}</h1>
<div class="divider" />
<div class="action">
<a
class="link"
:href="withBase(root)"
:aria-label="theme.notFound?.linkLabel ?? 'go to home'"
>
{{ theme.notFound?.linkText ?? 'Take me home' }}
</a>
</div>
<blockquote class="quote">
{{
theme.notFound?.quote ??
"虽然你迷路了,但是这是一个扫雷小游戏"
}}
</blockquote>
<Sweep />
</div>
</template>
<style scoped>
.NotFound {
padding: 64px 24px 96px;
text-align: center;
}
@media (min-width: 768px) {
.NotFound {
padding: 96px 32px 168px;
}
}
.code {
line-height: 128px;
font-size: 128px;
font-weight: 500;
}
.title {
padding-top: 12px;
letter-spacing: 2px;
line-height: 20px;
font-size: 35px;
font-weight: 700;
}
.divider {
margin: 24px auto 1px;
width: 64px;
height: 1px;
background-color: var(--vp-c-divider);
}
.quote {
margin: 0 auto;
padding-top: 20px;
max-width: 256px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
}
.action {
padding-top: 20px;
}
.link {
display: inline-block;
border: 1px solid var(--vp-c-brand);
border-radius: 16px;
padding: 3px 16px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-brand);
transition:
border-color 0.25s,
color 0.25s;
}
.link:hover {
border-color: var(--vp-c-brand-dark);
color: var(--vp-c-brand-dark);
}
</style>

View File

@@ -0,0 +1,183 @@
<script lang="ts" setup>
import { ref, onMounted, watch } from 'vue'
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
import { APPEARANCE_KEY } from 'vitepress/dist/client/shared'
import VPSwitch from 'vitepress/dist/client/theme-default/components/VPSwitch.vue'
import VPIconSun from 'vitepress/dist/client/theme-default/components/icons/VPIconSun.vue'
import VPIconMoon from 'vitepress/dist/client/theme-default/components/icons/VPIconMoon.vue'
const { site, isDark } = useData()
const checked = ref(false)
const toggle = typeof localStorage !== 'undefined' ? useAppearance() : () => {}
onMounted(() => {
checked.value = document.documentElement.classList.contains('dark')
})
// @ts-expect-error: Transition API
const isAppearanceTransition = document.startViewTransition &&
!window.matchMedia(`(prefers-reduced-motion: reduce)`).matches
function useAppearance() {
const query = window.matchMedia('(prefers-color-scheme: dark)')
const classList = document.documentElement.classList
let userPreference = localStorage.getItem(APPEARANCE_KEY)
let isDark =
(site.value.appearance === 'dark' && userPreference == null) ||
(userPreference === 'auto' || userPreference == null
? query.matches
: userPreference === 'dark')
query.onchange = (e) => {
if (userPreference === 'auto') {
setClass((isDark = e.matches))
}
}
function toggle(event: MouseEvent) {
if (!isAppearanceTransition) {
setClass((isDark = !isDark))
userPreference = isDark
? query.matches ? 'auto' : 'dark'
: query.matches ? 'light' : 'auto'
localStorage.setItem(APPEARANCE_KEY, userPreference)
return
}
const x = event.clientX
const y = event.clientY
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
)
// @ts-expect-error: Transition API
const transition = document.startViewTransition(() => {
setClass((isDark = !isDark))
userPreference = isDark
? query.matches ? 'auto' : 'dark'
: query.matches ? 'light' : 'auto'
localStorage.setItem(APPEARANCE_KEY, userPreference)
})
transition.ready.then(() => {
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
]
document.documentElement.animate(
{
clipPath: isDark ? clipPath : [...clipPath].reverse(),
},
{
duration: 300,
easing: 'ease-in',
pseudoElement: isDark ? '::view-transition-new(root)' : '::view-transition-old(root)',
},
)
})
}
function setClass(dark: boolean): void {
const css = document.createElement('style')
css.type = 'text/css'
css.appendChild(
document.createTextNode(
`:not(.VPSwitchAppearance):not(.VPSwitchAppearance *) {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}`
)
)
document.head.appendChild(css)
checked.value = dark
classList[dark ? 'add' : 'remove']('dark')
const _ = window.getComputedStyle(css).opacity
document.head.removeChild(css)
}
return toggle
}
watch(checked, (newIsDark) => {
isDark.value = newIsDark
})
</script>
<template>
<label title="toggle dark mode">
<VPSwitch
class="VPSwitchAppearance"
:class="{ 'VPSwitchAppearanceTransition': isAppearanceTransition }"
:aria-checked="checked"
@click="toggle"
>
<VPIconSun class="sun" />
<VPIconMoon class="moon" />
</VPSwitch>
</label>
</template>
<style scoped>
.sun {
opacity: 1;
}
.moon {
opacity: 0;
}
.dark .sun {
opacity: 0;
}
.dark .moon {
opacity: 1;
}
.VPSwitchAppearance.VPSwitchAppearanceTransition {
width: 22px;
}
.dark .VPSwitchAppearance:not(.VPSwitchAppearanceTransition) :deep(.check) {
/*rtl:ignore*/
transform: translateX(18px);
}
</style>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 9999;
}
::view-transition-new(root) {
z-index: 1;
}
.dark::view-transition-old(root) {
z-index: 1;
}
.dark::view-transition-new(root) {
z-index: 9999;
}
</style>

View File

@@ -0,0 +1,73 @@
<script setup>
defineProps(
{
block: {
type: Object,
required: true,
},
},
['block']
)
const numberColors = [
'text-transparent',
'text-blue-500',
'text-green-500',
'text-yellow-500',
'text-orange-500',
'text-red-500',
'text-purple-500',
'text-pink-500',
'text-teal-500',
]
function getBlockClass(block) {
if (block.flagged)
return 'bg-gray-500-10'
if (!block.revealed)
return 'bg-gray-500-10 hover:bg-gray-500-20'
return block.mine
? 'bg-red-500-50'
: numberColors[block.adjacentMines]
}
</script>
<style>
.text-transparent { color: transparent; }
.text-blue-500 { color: #3b82f6; }
.text-green-500 { color: #10b981; }
.text-yellow-500 { color: #f59e0b; }
.text-orange-500 { color: #f97316; }
.text-red-500 { color: #ef4444; }
.text-red { color: rgba(248, 113, 113); }
.text-purple-500 { color: #8b5cf6; }
.text-pink-500 { color: #ec4899; }
.text-teal-500 { color: #14b8a6; }
.bg-gray-500-10 { background-color: rgba(107, 114, 128, 0.1); }
.bg-gray-500-20 { background-color: rgba(107, 114, 128, 0.2); }
.bg-red-500-50 { background-color: rgba(239, 68, 68, 0.5); }
.font-600 { font-weight: 600; }
.button-block { width: 30px; height: 30px; }
</style>
<template>
<button
style="display: flex; align-items: center; justify-content: center; min-width: 2rem; min-height: 2rem; margin: 1px; border: 0.5px solid rgba(166, 166, 166, 0.1);"
:class="getBlockClass(block)"
>
<template v-if="block.flagged">
<div class="text-red button-block">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="currentColor" d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6h-5.6Z"/></svg>
</div>
</template>
<template v-else-if="block.revealed">
<div v-if="block.mine" class="button-block">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="currentColor" d="M23 13v-2h-3.07a7.988 7.988 0 0 0-1.62-3.9l2.19-2.17l-1.43-1.43l-2.17 2.19A7.988 7.988 0 0 0 13 4.07V1h-2v3.07c-1.42.18-2.77.74-3.9 1.62L4.93 3.5L3.5 4.93L5.69 7.1A7.988 7.988 0 0 0 4.07 11H1v2h3.07c.18 1.42.74 2.77 1.62 3.9L3.5 19.07l1.43 1.43l2.17-2.19c1.13.88 2.48 1.44 3.9 1.62V23h2v-3.07c1.42-.18 2.77-.74 3.9-1.62l2.17 2.19l1.43-1.43l-2.19-2.17a7.988 7.988 0 0 0 1.62-3.9H23M12 8a4 4 0 0 0-4 4H6a6 6 0 0 1 6-6v2Z"/></svg>
</div>
<div v-else class="font-600">
{{ block.adjacentMines }}
</div>
</template>
</button>
</template>

View File

@@ -0,0 +1,161 @@
<script setup>
import { GamePlay } from '../composables/logic.js'
import { useNow, useStorage } from '@vueuse/core'
import { watchEffect } from 'vue'
import MineBlock from './MineBlock.vue'
import Confetti from './Confetti.vue'
const play = new GamePlay(9, 9, 10)
const now = $(useNow())
const timerMS = $computed(() => Math.round(((play.state.value.endMS || +now) - play.state.value.startMS) / 1000))
useStorage('vuesweeper-state', play.state)
const state = $computed(() => play.board)
const mineRest = $computed(() => {
if (!play.state.value.mineGenerated)
return play.mines
return play.blocks.reduce((a, b) => a + (b.mine ? 1 : 0) - (b.flagged ? 1 : 0), 0)
})
function newGame(difficulty) {
switch (difficulty) {
case 'very easy':
play.reset(3, 3, 1)
break
case 'easy':
play.reset(9, 9, 10)
break
case 'medium':
play.reset(16, 16, 40)
break
case 'hard':
play.reset(16, 30, 99)
break
}
}
watchEffect(() => {
play.checkGameState()
})
</script>
<template>
<div>
<div class="flex gap1 justify-center p4">
<button class="btn" @click="play.reset()">
New Game
</button>
<button class="btn" @click="newGame('very easy')">
Very Easy
</button>
<button class="btn" @click="newGame('easy')">
Easy
</button>
<button class="btn" @click="newGame('medium')">
Medium
</button>
<button class="btn" @click="newGame('hard')">
Hard
</button>
</div>
<div class="flex gap-10 justify-center">
<div class="text-2xl flex gap-1 items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 32 32"><path fill="currentColor" d="M15 11h2v9h-2zm-2-9h6v2h-6z"/><path fill="currentColor" d="m28 9l-1.42-1.41l-2.25 2.25a10.94 10.94 0 1 0 1.18 1.65ZM16 26a9 9 0 1 1 9-9a9 9 0 0 1-9 9Z"/></svg>
{{ timerMS }}
</div>
<div class="text-2xl flex gap-1 items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24"><path fill="currentColor" d="M23 13v-2h-3.07a7.988 7.988 0 0 0-1.62-3.9l2.19-2.17l-1.43-1.43l-2.17 2.19A7.988 7.988 0 0 0 13 4.07V1h-2v3.07c-1.42.18-2.77.74-3.9 1.62L4.93 3.5L3.5 4.93L5.69 7.1A7.988 7.988 0 0 0 4.07 11H1v2h3.07c.18 1.42.74 2.77 1.62 3.9L3.5 19.07l1.43 1.43l2.17-2.19c1.13.88 2.48 1.44 3.9 1.62V23h2v-3.07c1.42-.18 2.77-.74 3.9-1.62l2.17 2.19l1.43-1.43l-2.19-2.17a7.988 7.988 0 0 0 1.62-3.9H23M12 8a4 4 0 0 0-4 4H6a6 6 0 0 1 6-6v2Z"/></svg>
{{ mineRest }}
</div>
</div>
<div class="p5 w-full overflow-auto">
<div
v-for="row, y in state"
:key="y"
class="flex items-center justify-center w-max ma"
>
<MineBlock
v-for="block, x in row" :key="x"
:block="block"
@click="play.onClick(block)"
@dblclick="play.autoExpand(block)"
@contextmenu.prevent="play.onRightClick(block)"
/>
</div>
</div>
<!-- <div flex="~ gap-1" justify-center>
<button btn @click="toggleDev()">
{{ isDev ? 'DEV' : 'NORMAL' }}
</button>
</div> -->
<Confetti :passed="play.state.value.status === 'won'" />
</div>
</template>
<style>
.gap1 {
gap: 0.25rem;
}
.gap-1 {
gap: 0.25rem;
}
.gap-10 {
gap: 2.5rem;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.items-center {
align-items: center;
}
.text-2xl {
font-size: 1.5rem;
}
.btn {
background-color: var(--vp-button-brand-bg);
border: 1px solid var(--vp-c-brand-light);
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 0.25rem;
cursor: pointer;
color: #fff;
transition: all 0.1s ease-in-out;
}
.btn:hover {
background-color: var(--vp-c-brand-light);
border-color: var(--vp-c-brand-light);
transition: all 0.1s ease-in-out;
}
.btn:dark {
background-color: var(--vp-c-brand-dark);
border-color: var(--vp-c-brand-light);
transition: all 0.1s ease-in-out;
}
.p4 {
padding: 1rem;
}
.p5 {
padding: 1.25rem;
}
.w-full {
width: 100%;
}
.w-max {
width: max-content;
}
.overflow-auto {
overflow: auto;
}
.ma {
margin: auto;
}
</style>

View File

@@ -0,0 +1,210 @@
import { ref } from 'vue';
const directions = [
[1, 1],
[1, 0],
[1, -1],
[0, -1],
[-1, -1],
[-1, 0],
[-1, 1],
[0, 1],
];
export class GamePlay {
state = ref();
constructor(width, height, mines) {
this.width = width;
this.height = height;
this.mines = mines;
this.reset();
}
get board() {
return this.state.value.board;
}
get blocks() {
return this.state.value.board.flat();
}
reset(width = this.width, height = this.height, mines = this.mines) {
this.width = width;
this.height = height;
this.mines = mines;
this.state.value = {
startMS: +Date.now(),
endMS: undefined, // 确保结束时间戳被重置
mineGenerated: false,
status: 'play',
board: Array.from({ length: this.height }, (_, y) =>
Array.from({ length: this.width }, (_, x) => ({
x,
y,
mine: false, // 初始化 mine 属性
flagged: false, // 初始化 flagged 属性
adjacentMines: 0,
revealed: false,
}),
),
),
};
}
randomRange(min, max) {
return Math.random() * (max - min) + min;
}
randomInt(min, max) {
return Math.round(this.randomRange(min, max));
}
generateMines(state, initial) {
const placeRandom = () => {
const x = this.randomInt(0, this.width - 1);
const y = this.randomInt(0, this.height - 1);
const block = state[y][x];
if (Math.abs(initial.x - block.x) <= 1 && Math.abs(initial.y - block.y) <= 1)
return false;
if (block.mine)
return false;
block.mine = true;
return true;
};
Array.from({ length: this.mines }, () => null)
.forEach(() => {
let placed = false;
let attempts = 0;
const maxAttempts = 1000;
while (!placed) {
if (attempts++ > maxAttempts) {
this.reset();
break;
}
placed = placeRandom();
}
});
this.updateNumbers();
}
updateNumbers() {
this.board.forEach((raw) => {
raw.forEach((block) => {
if (block.mine)
return;
this.getSiblings(block)
.forEach((b) => {
if (b.mine)
block.adjacentMines += 1;
});
});
});
}
expendZero(block) {
if (block.adjacentMines)
return;
this.getSiblings(block)
.forEach((s) => {
if (!s.revealed) {
s.revealed = true;
this.expendZero(s);
}
});
}
onRightClick(block) {
if (this.state.value.status !== 'play')
return;
if (block.revealed)
return;
block.flagged = !block.flagged;
}
onClick(block) {
if (this.state.value.status !== 'play')
return;
if (!this.state.value.mineGenerated) {
this.generateMines(this.board, block);
this.state.value.mineGenerated = true;
}
block.revealed = true;
if (block.mine) {
this.onGameOver('lost');
return;
}
this.expendZero(block);
}
getSiblings(block) {
return directions.map(([dx, dy]) => {
const x2 = block.x + dx;
const y2 = block.y + dy;
if (x2 < 0 || x2 >= this.width || y2 < 0 || y2 >= this.height)
return undefined;
return this.board[y2][x2];
})
.filter(Boolean);
}
showAllMines() {
this.board.flat().forEach((i) => {
if (i.mine)
i.revealed = true;
});
}
checkGameState() {
if (!this.state.value.mineGenerated)
return;
const blocks = this.board.flat();
if (blocks.every(block => block.revealed || block.flagged || block.mine)) {
if (blocks.some(block => block.flagged && !block.mine))
this.onGameOver('lost');
else
this.onGameOver('won');
}
}
autoExpand(block) {
const siblings = this.getSiblings(block);
const flags = siblings.reduce((a, b) => a + (b.flagged ? 1 : 0), 0);
const notRevealed = siblings.reduce((a, b) => a + (!b.revealed && !b.flagged ? 1 : 0), 0);
if (flags === block.adjacentMines) {
siblings.forEach((i) => {
if (i.revealed || i.flagged)
return;
i.revealed = true;
this.expendZero(i);
if (i.mine)
this.onGameOver('lost');
});
}
const missingFlags = block.adjacentMines - flags;
if (notRevealed === missingFlags) {
siblings.forEach((i) => {
if (!i.revealed && !i.flagged)
i.flagged = true;
});
}
}
onGameOver(status) {
this.state.value.status = status;
this.state.value.endMS = +Date.now();
if (status === 'lost') {
this.showAllMines();
setTimeout(() => {
alert('lost');
}, 10);
}
}
}

View File

@@ -1,668 +1,62 @@
import { defineConfig } from 'vitepress'
import mathjax3 from 'markdown-it-mathjax3';
const customElements = [
'mjx-container',
'mjx-assistive-mml',
'math',
'maction',
'maligngroup',
'malignmark',
'menclose',
'merror',
'mfenced',
'mfrac',
'mi',
'mlongdiv',
'mmultiscripts',
'mn',
'mo',
'mover',
'mpadded',
'mphantom',
'mroot',
'mrow',
'ms',
'mscarries',
'mscarry',
'mscarries',
'msgroup',
'mstack',
'mlongdiv',
'msline',
'mstack',
'mspace',
'msqrt',
'msrow',
'mstack',
'mstack',
'mstyle',
'msub',
'msup',
'msubsup',
'mtable',
'mtd',
'mtext',
'mtr',
'munder',
'munderover',
'semantics',
'math',
'mi',
'mn',
'mo',
'ms',
'mspace',
'mtext',
'menclose',
'merror',
'mfenced',
'mfrac',
'mpadded',
'mphantom',
'mroot',
'mrow',
'msqrt',
'mstyle',
'mmultiscripts',
'mover',
'mprescripts',
'msub',
'msubsup',
'msup',
'munder',
'munderover',
'none',
'maligngroup',
'malignmark',
'mtable',
'mtd',
'mtr',
'mlongdiv',
'mscarries',
'mscarry',
'msgroup',
'msline',
'msrow',
'mstack',
'maction',
'semantics',
'annotation',
'annotation-xml',
];
// import { defineConfig } from 'vitepress'
import { withMermaid } from "vitepress-plugin-mermaid-xyxsw";
import { main_sidebar, chapter2, chapter3, chapter4, chapter5, chapter6, chapter7, chapter8, chapter9 } from './sidebar.js';
import { nav } from './nav.js';
import PanguPlugin from 'markdown-it-pangu'
import { fileURLToPath, URL } from 'node:url'
import VueMacros from 'unplugin-vue-macros/vite'
// https://vitepress.dev/reference/site-config
export default defineConfig({
export default withMermaid({
lang: 'zh-CN',
title: "HDU-CS-WIKI",
description: "HDU计算机科学讲义",
description: "HDU 计算机科学讲义",
lastUpdated: true,
head: [['script', { async: "async", src: 'https://umami.hdu-cs.wiki/script.js', "data-website-id": "3f11687a-faae-463a-b863-6127a8c28301", "data-domains": "wiki.xyxsw.site,hdu-cs.wiki" }]],
cleanUrls: true,
head: [
['script', { async: "async", src: 'https://umami.hdu-cs.wiki/script.js', "data-website-id": "3f11687a-faae-463a-b863-6127a8c28301", "data-domains": "wiki.xyxsw.site,hdu-cs.wiki" }],
['link', { rel: 'icon', href: '/favicon.ico' }],
["meta", { "name": "description", "content": "HDU计算机科学讲义" }],
["meta", { "property": "og:url", "content": "https://hdu-cs.wiki/" }],
["meta", { "property": "og:type", "content": "website" }],
["meta", { "property": "og:title", "content": "HDU-CS-WIKI | HDU-CS-WIKI" }],
["meta", { "property": "og:description", "content": "HDU计算机科学讲义" }],
["meta", { "property": "og:image", "content": "https://cdn.xyxsw.site/og-img.png" }],
["meta", { "name": "twitter:card", "content": "summary_large_image" }],
["meta", { "property": "twitter:domain", "content": "hdu-cs.wiki" }],
["meta", { "property": "twitter:url", "content": "https://hdu-cs.wiki/" }],
["meta", { "name": "twitter:title", "content": "HDU-CS-WIKI | HDU-CS-WIKI" }],
["meta", { "name": "twitter:description", "content": "HDU计算机科学讲义" }],
["meta", { "name": "twitter:image", "content": "https://cdn.xyxsw.site/og-img.png" }],
["link", { "rel": "apple-touch-icon", "sizes": "180x180", "href": "/apple-touch-icon.png" }],
["link", { "rel": "icon", "type": "image/png", "sizes": "32x32", "href": "/favicon-32x32.png" }],
["link", { "rel": "icon", "type": "image/png", "sizes": "16x16", "href": "/favicon-16x16.png" }],
["link", { "rel": "manifest", "href": "/site.webmanifest" }],
["link", { "rel": "mask-icon", "href": "/safari-pinned-tab.svg", "color": "#5bbad5" }],
["meta", { "name": "msapplication-TileColor", "content": "#2b5797" }],
],
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: '首页', link: '/' },
],
nav: nav(),
sidebar: [
{
text: '简介',
collapsed: true,
items: [
{ text: '简介', link: '/简介' },
{ text: '使用指南', link: '/使用指南' },
]
sidebar: {
'/': main_sidebar(),
'/2.高效学习/': chapter2(),
'/3.编程思维体系构建/': chapter3(),
'/4.人工智能/': chapter4(),
'/5.富有生命的嵌入式/': chapter5(),
'/6.计算机安全/': chapter6(),
'/7.网络应用开发/': chapter7(),
'/8.基础学科/': chapter8(),
'/9.计算机网络/': chapter9(),
},
{
text: '1.杭电生存指南(最重要模块)',
collapsed: true,
items: [
{ text: '1.1人文社科的重要性(韩健夫老师寄语)', link: '/1.杭电生存指南/1.1人文社科的重要性(韩健夫老师寄语)' },
{ text: '1.2竞赛指北', link: '/1.杭电生存指南/1.2竞赛指北' },
{ text: '1.3导师选择', link: '/1.杭电生存指南/1.3导师选择' },
{ text: '1.4小心项目陷阱', link: '/1.杭电生存指南/1.4小心项目陷阱' },
{ text: '1.5小组作业避雷指南', link: '/1.杭电生存指南/1.5小组作业避雷指南' },
{ text: '1.6正确解读GPA', link: '/1.杭电生存指南/1.6正确解读GPA' },
{ text: '1.7杭电出国自救指南', link: '/1.杭电生存指南/1.7杭电出国自救指南' },
{ text: '1.8转专业二三事', link: '/1.杭电生存指南/1.8转专业二三事' },
{ text: '1.9问题专题:好想进入实验室', link: '/1.杭电生存指南/1.9问题专题:好想进入实验室' },
{ text: '1.10如何读论文', link: '/1.杭电生存指南/1.10如何读论文' },
{ text: '1.11陷入虚无主义?进来看看吧', link: '/1.杭电生存指南/1.11陷入虚无主义?进来看看吧' },
{ text: '1.12程序员如何活久一点', link: '/1.杭电生存指南/1.12程序员如何活久一点' },
{ text: '1.13选课原则与抢课技巧', link: '/1.杭电生存指南/1.13选课原则与抢课技巧' },
]
},
{
text: '2.高效学习',
collapsed: true,
items: [
{ text: '2.高效学习', link: '/2.高效学习/2.高效学习' },
{
text: '2.1高效的前提:摆脱高中思维',
collapsed: true,
items: [
{ text: '2.1高效的前提:摆脱高中思维', link: '/2.高效学习/2.1高效的前提:摆脱高中思维' },
{ text: '2.1.1悲壮的学习方式', link: '/2.高效学习/2.1.1悲壮的学习方式' },
{ text: '2.1.2浮躁的心理状态', link: '/2.高效学习/2.1.2浮躁的心理状态' },
{ text: '2.1.3错误的提问姿态', link: '/2.高效学习/2.1.3错误的提问姿态' },
{ text: '2.1.4书籍的盲目崇拜', link: '/2.高效学习/2.1.4书籍的盲目崇拜' },
{ text: '2.1.5错误的学习配比', link: '/2.高效学习/2.1.5错误的学习配比' },
]
},
{ text: '2.2优雅的使用工具', link: '/2.高效学习/2.2优雅的使用工具' },
{
text: '2.3高效的信息检索',
collapsed: true,
items: [
{ text: '2.3高效的信息检索', link: '/2.高效学习/2.3高效的信息检索' },
{ text: '2.3.1阅读文档B百度爬', link: '/2.高效学习/2.3.1阅读文档B百度爬' },
{ text: '2.3.2检索论文核心内容', link: '/2.高效学习/2.3.2检索论文核心内容' },
{ text: '2.3.3优秀的开源社区', link: '/2.高效学习/2.3.3优秀的开源社区' },
{ text: '补充:为什么不要用百度', link: '/2.高效学习/补充:为什么不要用百度' },
]
},
{ text: '2.4优雅的记笔记', link: '/2.高效学习/2.4优雅的记笔记' },
{ text: '2.5以理工科的方式阅读英语', link: '/2.高效学习/2.5以理工科的方式阅读英语' },
]
},
{
text: '3.编程思维体系构建',
collapsed: true,
items: [
{ text: '3.编程思维体系构建', link: '/3.编程思维体系构建/3.编程思维体系构建' },
{ text: '3.0 编程入门之道', link: '/3.编程思维体系构建/3.0 编程入门之道' },
{ text: '3.1该使用哪个编辑器???', link: '/3.编程思维体系构建/3.1该使用哪个编辑器???' },
{
text: '3.2算法杂谈',
collapsed: true,
items: [
{ text: '3.2算法杂谈', link: '/3.编程思维体系构建/3.2算法杂谈' },
{ text: '3.2.1为什么要选择ACM——谈谈我与ACM', link: '/3.编程思维体系构建/3.2.1为什么要选择ACM——谈谈我与ACM' },
{ text: '3.2.2手把手教你学算法——如何使用OJOnline Judge', link: '/3.编程思维体系构建/3.2.2手把手教你学算法——如何使用OJOnline Judge' },
{ text: '3.2.3ACM 竞赛从入门到入坟', link: '/3.编程思维体系构建/3.2.3ACM 竞赛从入门到入坟' },
]
},
{ text: '3.3如何选择编程语言', link: '/3.编程思维体系构建/3.3如何选择编程语言' },
{
text: '3.4C语言',
collapsed: true,
items: [
{ text: '3.4C语言', link: '/3.编程思维体系构建/3.4C语言' },
{ text: '3.4.1FAQ:常见问题', link: '/3.编程思维体系构建/3.4.1FAQ:常见问题' },
{ text: '3.4.2用什么写 C 语言', link: '/3.编程思维体系构建/3.4.2用什么写 C 语言' },
{ text: '3.4.3解决编程问题的普适性过程', link: '/3.编程思维体系构建/3.4.3解决编程问题的普适性过程' },
{ text: '3.4.4C语言前置概念学习', link: '/3.编程思维体系构建/3.4.4C语言前置概念学习' },
{
text: '3.4.5阶段一:编程属性',
collapsed: true,
items: [
{ text: '3.4.5阶段一:编程属性', link: '/3.编程思维体系构建/3.4.5阶段一:编程属性' },
{ text: '3.4.5.1C语言自测标准——链表', link: '/3.编程思维体系构建/3.4.5.1C语言自测标准——链表' },
]
},
{
text: '3.4.6阶段二文字冒险cool',
collapsed: true,
items: [
{ text: '3.4.6阶段二文字冒险cool', link: '/3.编程思维体系构建/3.4.6阶段二文字冒险cool' },
{ text: '3.4.6.1.开始冒险', link: '/3.编程思维体系构建/3.4.6.1.开始冒险' },
{ text: '3.4.6.2.探索未知', link: '/3.编程思维体系构建/3.4.6.2.探索未知' },
{ text: '3.4.6.3.指明地点', link: '/3.编程思维体系构建/3.4.6.3.指明地点' },
{ text: '3.4.6.4.创建对象', link: '/3.编程思维体系构建/3.4.6.4.创建对象' },
{ text: '3.4.6.5.捡起物品', link: '/3.编程思维体系构建/3.4.6.5.捡起物品' },
{ text: '3.4.6.6.绘制地图', link: '/3.编程思维体系构建/3.4.6.6.绘制地图' },
{ text: '3.4.6.7.增大距离', link: '/3.编程思维体系构建/3.4.6.7.增大距离' },
{ text: '3.4.6.8.移动方向', link: '/3.编程思维体系构建/3.4.6.8.移动方向' },
{ text: '3.4.6.9.练习:生成代码', link: '/3.编程思维体系构建/3.4.6.9.练习:生成代码' },
{ text: '3.4.6.10.增添属性', link: '/3.编程思维体系构建/3.4.6.10.增添属性' },
{ text: '3.4.6.11.设置条件', link: '/3.编程思维体系构建/3.4.6.11.设置条件' },
{ text: '3.4.6.12.开启关闭', link: '/3.编程思维体系构建/3.4.6.12.开启关闭' },
{ text: '3.4.6.13.编写解析器', link: '/3.编程思维体系构建/3.4.6.13.编写解析器' },
{ text: '3.4.6.14.丰富命令', link: '/3.编程思维体系构建/3.4.6.14.丰富命令' },
{ text: '3.4.6.15.赋予明暗', link: '/3.编程思维体系构建/3.4.6.15.赋予明暗' },
{ text: '3.4.6.16.结语:你终将自由', link: '/3.编程思维体系构建/3.4.6.16.结语:你终将自由' },
]
},
{
text: '3.4.7C基础知识杂谈',
collapsed: true,
items: [
{ text: '3.4.7C基础知识杂谈', link: '/3.编程思维体系构建/3.4.7C基础知识杂谈' },
{ text: '3.4.7.1GDB初探索(编程可阅览)', link: '/3.编程思维体系构建/3.4.7.1GDB初探索(编程可阅览)' },
{ text: '3.4.7.1.1调试理论', link: '/3.编程思维体系构建/3.4.7.1.1调试理论' },
{ text: '3.4.7.2C的历史问题undefined behavior', link: '/3.编程思维体系构建/3.4.7.2C的历史问题undefined behavior' },
{ text: '3.4.7.3C编译器干了什么', link: '/3.编程思维体系构建/3.4.7.3C编译器干了什么' },
{ text: '3.4.7.4Inline Assembly与链接加载', link: '/3.编程思维体系构建/3.4.7.4Inline Assembly与链接加载' },
]
},
]
},
{ text: '3.5git与github', link: '/3.编程思维体系构建/3.5git与github' },
{
text: '3.6Python(灵巧的胶水)',
collapsed: true,
items: [
{ text: '3.6Python(灵巧的胶水)', link: '/3.编程思维体系构建/3.6Python(灵巧的胶水)' },
{ text: '3.6.1从CS61A看编程语言学习', link: '/3.编程思维体系构建/3.6.1从CS61A看编程语言学习' },
{ text: '3.6.2环境配置', link: '/3.编程思维体系构建/3.6.2环境配置' },
{ text: '3.6.3安装python', link: '/3.编程思维体系构建/3.6.3安装python' },
{
text: '3.6.4Python for fun',
collapsed: true,
items: [
{ text: '3.6.4Python for fun', link: '/3.编程思维体系构建/3.6.4Python for fun' },
{ text: '3.6.4.0阶段零Python解释器', link: '/3.编程思维体系构建/3.6.4.0阶段零Python解释器' },
{ text: '3.6.4.1阶段一:熟悉语句', link: '/3.编程思维体系构建/3.6.4.1阶段一:熟悉语句' },
{ text: '3.6.4.2阶段二:递归操作', link: '/3.编程思维体系构建/3.6.4.2阶段二:递归操作' },
{ text: '3.6.4.3阶段三:数据抽象', link: '/3.编程思维体系构建/3.6.4.3阶段三:数据抽象' },
{ text: '3.6.4.4阶段四:高阶函数', link: '/3.编程思维体系构建/3.6.4.4阶段四:高阶函数' },
{ text: '3.6.4.5阶段五:迭代生成', link: '/3.编程思维体系构建/3.6.4.5阶段五:迭代生成' },
{ text: '3.6.4.6结语', link: '/3.编程思维体系构建/3.6.4.6结语' },
]
}
]
},
{ text: '3.X 聊聊设计模式和程序设计', link: '/3.编程思维体系构建/3.X 聊聊设计模式和程序设计' },
{
text: '3.Y 附加模块Linux',
collapsed: true,
items: [
{ text: '3.Y 附加模块Linux', link: '/3.编程思维体系构建/3.Y 附加模块Linux' },
{ text: '3.Y.1VMware的安装与安装Ubuntu22.04系统', link: '/3.编程思维体系构建/3.Y.1VMware的安装与安装Ubuntu22.04系统' },
{ text: '3.Y.2WSL的安装', link: '/3.编程思维体系构建/3.Y.2WSL的安装' },
{ text: '3.Y.3Linux初探索', link: '/3.编程思维体系构建/3.Y.3Linux初探索' },
{ text: '3.Y.4Vim初探索', link: '/3.编程思维体系构建/3.Y.4Vim初探索' },
{ text: '3.Y.5linux小任务', link: '/3.编程思维体系构建/3.Y.5linux小任务' },
]
}
]
},
{
text: '4.人工智能',
collapsed: true,
items: [
{ text: '4.人工智能', link: '/4.人工智能/4.人工智能' },
{ text: '4.1前言', link: '/4.人工智能/4.1前言' },
{ text: '4.2机器学习AI快速入门quick start', link: '/4.人工智能/4.2机器学习AI快速入门quick start' },
{
text: '4.3人工智能导论及机器学习入门',
collapsed: true,
items: [
{ text: '4.3人工智能导论及机器学习入门', link: '/4.人工智能/4.3人工智能导论及机器学习入门' },
{
text: '4.3.1搜索',
collapsed: true,
items: [
{ text: '4.3.1搜索', link: '/4.人工智能/4.3.1搜索' },
{ text: '4.3.1.1程序示例——maze迷宫解搜索', link: '/4.人工智能/4.3.1.1程序示例——maze迷宫解搜索' },
{ text: '4.3.1.2项目Tic-Tac-Toe井字棋', link: '/4.人工智能/4.3.1.2项目Tic-Tac-Toe井字棋' },
]
},
{
text: '4.3.2知识推理',
collapsed: true,
items: [
{ text: '4.3.2知识推理', link: '/4.人工智能/4.3.2知识推理' },
{ text: '4.3.2.1程序示例——命题逻辑与模型检测', link: '/4.人工智能/4.3.2.1程序示例——命题逻辑与模型检测' },
{ text: '4.3.2.2项目:扫雷,骑士与流氓问题', link: '/4.人工智能/4.3.2.2项目:扫雷,骑士与流氓问题' },
]
},
{
text: '4.3.3不确定性问题',
collapsed: true,
items: [
{ text: '4.3.3不确定性问题', link: '/4.人工智能/4.3.3不确定性问题' },
{ text: '4.3.3.1程序示例', link: '/4.人工智能/4.3.3.1程序示例' },
{ text: '4.3.3.2项目:遗传', link: '/4.人工智能/4.3.3.2项目:遗传' },
]
},
]
},
{ text: '4.4FAQ:常见问题', link: '/4.人工智能/4.4FAQ:常见问题' },
{
text: '4.6深度学习',
collapsed: true,
items: [
{ text: '4.6深度学习', link: '/4.人工智能/4.6深度学习' },
{ text: '4.6.1工欲善其事,必先利其器', link: '/4.人工智能/4.6.1工欲善其事,必先利其器' },
{ text: '4.6.2你可能会需要的术语介绍', link: '/4.人工智能/4.6.2你可能会需要的术语介绍' },
{ text: '4.6.3深度学习快速入门', link: '/4.人工智能/4.6.3深度学习快速入门' },
{ text: '4.6.4Pytorch安装', link: '/4.人工智能/4.6.4Pytorch安装' },
{
text: '4.6.5计算机视觉CV',
collapsed: true,
items: [
{ text: '4.6.5计算机视觉CV', link: '/4.人工智能/4.6.5计算机视觉CV' },
{ text: '4.6.5.1CV领域任务(研究目标)', link: '/4.人工智能/4.6.5.1CV领域任务(研究目标)' },
{
text: '4.6.5.2CV中的数据预处理torchvision',
collapsed: true,
items: [
{ text: '4.6.5.2CV中的数据预处理torchvision', link: '/4.人工智能/4.6.5.2CV中的数据预处理torchvision' },
{ text: '4.6.5.2.1数据读取', link: '/4.人工智能/4.6.5.2.1数据读取' },
{ text: '4.6.5.2.2数据增强', link: '/4.人工智能/4.6.5.2.2数据增强' },
]
},
{
text: '4.6.5.3CV中的经典网络',
collapsed: true,
items: [
{ text: '4.6.5.3CV中的经典网络', link: '/4.人工智能/4.6.5.3CV中的经典网络' },
{ text: '4.6.5.3.1AlexNet', link: '/4.人工智能/4.6.5.3.1AlexNet' },
{ text: '4.6.5.3.2FCN', link: '/4.人工智能/4.6.5.3.2FCN' },
{ text: '4.6.5.3.3ResNet', link: '/4.人工智能/4.6.5.3.3ResNet' },
{ text: '4.6.5.3.4UNet', link: '/4.人工智能/4.6.5.3.4UNet' },
{ text: '4.6.5.3.5GAN', link: '/4.人工智能/4.6.5.3.5GAN' },
{ text: '4.6.5.3.6思考题参考', link: '/4.人工智能/4.6.5.3.6思考题参考' },
{ text: '4.6.5.3.7还要学更多?', link: '/4.人工智能/4.6.5.3.7还要学更多?' },
]
},
{
text: '4.6.5.4神经辐射场(NeRF)',
collapsed: true,
items: [
{ text: '4.6.5.4神经辐射场(NeRF)', link: '/4.人工智能/4.6.5.4神经辐射场(NeRF)' },
{ text: '4.6.5.4.1NeRF', link: '/4.人工智能/4.6.5.4.1NeRF' },
{ text: '4.6.5.4.2NeRF的改进方向', link: '/4.人工智能/4.6.5.4.2NeRF的改进方向' },
{ text: '4.6.5.4.3自制数据集的工具COLMAP', link: '/4.人工智能/4.6.5.4.3自制数据集的工具COLMAP' },
]
},
{
text: '4.6.5.5行人重识别(ReID)',
collapsed: true,
items: [
{ text: '4.6.5.5行人重识别(ReID)', link: '/4.人工智能/4.6.5.5行人重识别(ReID)' },
]
},
]
},
{
text: '4.6.6自然语言处理NLP',
collapsed: true,
items: [
{ text: '4.6.6自然语言处理NLP', link: '/4.人工智能/4.6.6自然语言处理NLP' },
{ text: '4.6.6.1NLP领域任务(研究目标)', link: '/4.人工智能/4.6.6.1NLP领域任务(研究目标)' },
{
text: '4.6.6.2推荐系统',
collapsed: true,
items: [
{ text: '4.6.6.2推荐系统', link: '/4.人工智能/4.6.6.2推荐系统' },
{ text: '4.6.6.2.1推荐系统经典模型综述', link: '/4.人工智能/4.6.6.2.1推荐系统经典模型综述' },
{
text: '4.6.6.2.2基于数据的角度,看待推荐系统的构造',
collapsed: true,
items: [
{ text: '4.6.6.2.2基于数据的角度,看待推荐系统的构造', link: '/4.人工智能/4.6.6.2.2基于数据的角度,看待推荐系统的构造' },
{ text: '4.6.6.2.2.1《推荐系统实践》读后的一些想法', link: '/4.人工智能/4.6.6.2.2.1《推荐系统实践》读后的一些想法' },
{ text: '4.6.6.2.2.2推荐系统概念解释 and 一个好的推荐系统', link: '/4.人工智能/4.6.6.2.2.2推荐系统概念解释 and 一个好的推荐系统' },
{ text: '4.6.6.2.2.3推荐系统实例', link: '/4.人工智能/4.6.6.2.2.3推荐系统实例' },
{ text: '4.6.6.2.2.4利用用户行为数据', link: '/4.人工智能/4.6.6.2.2.4利用用户行为数据' },
{ text: '4.6.6.2.2.5推荐系统冷启动', link: '/4.人工智能/4.6.6.2.2.5推荐系统冷启动' },
{ text: '4.6.6.2.2.6利用标签信息', link: '/4.人工智能/4.6.6.2.2.6利用标签信息' },
{ text: '4.6.6.2.2.7利用上下文信息', link: '/4.人工智能/4.6.6.2.2.7利用上下文信息' },
]
},
{ text: '4.6.6.2.3序列化推荐', link: '/4.人工智能/4.6.6.2.3序列化推荐' },
]
},
{ text: '4.6.6.3知识图谱', link: '/4.人工智能/4.6.6.3知识图谱' },
]
},
{
text: '4.6.7Transformer',
collapsed: true,
items: [
{ text: '4.6.7Transformer', link: '/4.人工智能/4.6.7Transformer' },
{ text: '4.6.7.1VIT', link: '/4.人工智能/4.6.7.1VIT' },
{ text: '4.6.7.2BERT', link: '/4.人工智能/4.6.7.2BERT' },
{ text: '4.6.7.3MAE', link: '/4.人工智能/4.6.7.3MAE' },
]
},
{
text: '4.6.8对比学习',
collapsed: true,
items: [
{ text: '4.6.8对比学习', link: '/4.人工智能/4.6.8对比学习' },
{ text: '4.6.8.1前言', link: '/4.人工智能/4.6.8.1前言' },
{ text: '4.6.8.2Inst Disc', link: '/4.人工智能/4.6.8.2Inst Disc' },
{ text: '4.6.8.3定义正负样本的方式', link: '/4.人工智能/4.6.8.3定义正负样本的方式' },
{ text: '4.6.8.4MoCo', link: '/4.人工智能/4.6.8.4MoCo' },
{ text: '4.6.8.5SimCLR', link: '/4.人工智能/4.6.8.5SimCLR' },
{ text: '4.6.8.6SwAV', link: '/4.人工智能/4.6.8.6SwAV' },
{ text: '4.6.8.7BYOL', link: '/4.人工智能/4.6.8.7BYOL' },
{ text: '4.6.8.8SimSiam', link: '/4.人工智能/4.6.8.8SimSiam' },
{ text: '4.6.8.9MoCo v3', link: '/4.人工智能/4.6.8.9MoCo v3' },
{ text: '4.6.8.10总结', link: '/4.人工智能/4.6.8.10总结' },
]
},
{
text: '4.6.9深度强化学习',
collapsed: true,
items: [
{ text: '4.6.9深度强化学习', link: '/4.人工智能/4.6.9深度强化学习' },
{ text: '4.6.9.1前言', link: '/4.人工智能/4.6.9.1前言' },
{ text: '4.6.9.2基础资料推荐', link: '/4.人工智能/4.6.9.2基础资料推荐' },
{ text: '4.6.9.3基本概念介绍', link: '/4.人工智能/4.6.9.3基本概念介绍' },
]
}
]
},
{ text: '4.7图网络略述intro&GCN', link: '/4.人工智能/4.7图网络略述intro&GCN' },
{ text: '4.8数据分析', link: '/4.人工智能/4.8数据分析' },
{ text: '4.9如何做研究', link: '/4.人工智能/4.9如何做研究' },
{ text: '4.10科研论文写作', link: '/4.人工智能/4.10科研论文写作' },
{ text: '4.11从 AI 到 智能系统 —— 从 LLMs 到 Agents', link: '/4.人工智能/4.11从 AI 到 智能系统 —— 从 LLMs 到 Agents' },
{ text: '4.12本章节内容的局限性', link: '/4.人工智能/4.12本章节内容的局限性' },
{ text: 'SRT社团介绍', link: '/4.人工智能/SRT' },
{
text: 'FunRec',
collapsed: true,
items: [
{ text: 'FunRec概述', link: '/4.人工智能/FunRec概述' },
{
text: '推荐系统概述',
collapsed: true,
items: [
{ text: '推荐系统的意义', link: '/4.人工智能/ch01/ch1.1.md' },
{ text: '推荐系统架构', link: '/4.人工智能/ch01/ch1.2.md' },
{ text: '推荐系统技术栈', link: '/4.人工智能/ch01/ch1.3.md' },
]
},
{
text: '推荐系统算法基础',
collapsed: true,
items: [
{
text: '经典召回模型',
collapsed: true,
items: [
{
text: '基于协同过滤的召回', collapsed: true, items: [
{ text: 'UserCF', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/usercf.md' },
{ text: 'ItemCF', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/itemcf.md' },
{ text: 'Swing', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/Swing.md' },
{ text: '矩阵分解', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/mf.md' },
]
},
{ text: 'FM召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/FM.md' },
{
text: 'item2vec召回系列', collapsed: true, items: [
{ text: 'word2vec原理', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/word2vec.md' },
{ text: 'item2vec召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/item2vec.md' },
{ text: 'Airbnb召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/Airbnb.md' },
]
},
{ text: 'YoutubeDNN召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/YoutubeDNN.md' },
{
text: '双塔召回', collapsed: true, items: [
{ text: '经典双塔', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/DSSM.md' },
{ text: 'Youtube双塔', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/YoutubeTwoTower.md' },
]
},
{
text: '图召回', collapsed: true, items: [
{ text: 'EGES', link: '/4.人工智能/ch02/ch2.1/ch2.1.3/EGES.md' },
{ text: 'PinSAGE', link: '/4.人工智能/ch02/ch2.1/ch2.1.3/PinSage.md' },
]
},
{
text: '序列召回', collapsed: true, items: [
{ text: 'MIND', link: '/4.人工智能/ch02/ch2.1/ch2.1.4/MIND.md' },
{ text: 'SDM', link: '/4.人工智能/ch02/ch2.1/ch2.1.4/SDM.md' },
]
},
{
text: '树模型召回', collapsed: true, items: [
{ text: 'TDM', link: '/4.人工智能/ch02/ch2.1/ch2.1.5/TDM.md' },
]
}
]
},
{
text: '经典排序模型',
collapsed: true,
items: [
{ text: 'GBDT+LR', link: '/4.人工智能/ch02/ch2.2/ch2.2.1.md' },
{
text: '特征交叉', collapsed: true, items: [
{ text: 'FM', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/FM.md' },
{ text: 'PNN', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/PNN.md' },
{ text: 'DCN', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/DCN.md' },
{ text: 'AutoInt', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/AutoInt.md' },
{ text: 'FiBiNET', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/FiBiNet.md' },
]
},
{
text: 'WideNDeep系列', collapsed: true, items: [
{ text: 'Wide&Deep', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/WideNDeep.md' },
{ text: 'NFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/NFM.md' },
{ text: 'AFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/AFM.md' },
{ text: 'DeepFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/DeepFM.md' },
{ text: 'xDeepFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/xDeepFM.md' },
]
},
{
text: '序列模型', collapsed: true, items: [
{ text: 'DIN', link: '/4.人工智能/ch02/ch2.2/ch2.2.4/DIN.md' },
{ text: 'DIEN', link: '/4.人工智能/ch02/ch2.2/ch2.2.4/DIEN.md' },
{ text: 'DSIN', link: '/4.人工智能/ch02/ch2.2/ch2.2.4/DSIN.md' },
]
},
{
text: '多任务学习', collapsed: true, items: [
{ text: '多任务学习概述', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/2.2.5.0.md' },
{ text: 'ESMM', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/ESMM.md' },
{ text: 'MMOE', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/MMOE.md' },
{ text: 'PLE', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/PLE.md' },
]
}
]
}
]
}
]
}
]
},
{
text: '5.富有生命的嵌入式',
collapsed: true,
items: [
{ text: '5.富有生命的嵌入式', link: '/5.富有生命的嵌入式/5.富有生命的嵌入式' },
{ text: '5.1嵌入式是什么?可以吃吗?', link: '/5.富有生命的嵌入式/5.1嵌入式是什么?可以吃吗?' },
{ text: '5.2New meaning of C', link: '/5.富有生命的嵌入式/5.2New meaning of C' },
{ text: '5.3还玩裸机?上操作系统!', link: '/5.富有生命的嵌入式/5.3还玩裸机?上操作系统!' },
]
},
{
text: '6.计算机安全',
collapsed: true,
items: [
{ text: '6.计算机安全', link: '/6.计算机安全/6.计算机安全' },
{
text: '6.1Web安全',
collapsed: true,
items: [
{ text: '6.1Web安全', link: '/6.计算机安全/6.1Web安全' },
{ text: '6.1.1SQL 注入', link: '/6.计算机安全/6.1.1SQL 注入' },
]
},
{
text: '6.2二进制安全',
collapsed: true,
items: [
{ text: '6.2二进制安全', link: '/6.计算机安全/6.2二进制安全' },
{ text: '6.2.1基础工具的使用', link: '/6.计算机安全/6.2.1基础工具的使用' },
{ text: '6.2.2软件破解、软件加固', link: '/6.计算机安全/6.2.2软件破解、软件加固' },
]
},
{ text: '6.3密码学', link: '/6.计算机安全/6.3密码学' },
{ text: '6.4安全杂项', link: '/6.计算机安全/6.4安全杂项' },
]
},
{
text: '7.网络应用开发',
collapsed: true,
items: [
{ text: '7.网络应用开发入门', link: '/7.网络应用开发/7.网络应用开发入门' },
{
text: '7.1WEB开发入门',
collapsed: true,
items: [
{ text: '7.1WEB开发入门', link: '/7.网络应用开发/7.1WEB开发入门' },
{
text: '7.1.1前端部分',
collapsed: true,
items: [
{ text: '7.1.1前端部分', link: '/7.网络应用开发/7.1.1前端部分' },
{ text: '7.1.1.1基础部分', link: '/7.网络应用开发/7.1.1.1基础部分' },
{ text: '7.1.1.2进阶部分', link: '/7.网络应用开发/7.1.1.2进阶部分' },
{ text: '7.1.1.3附录1前端介绍详细版', link: '/7.网络应用开发/7.1.1.3附录1前端介绍详细版' },
{ text: '7.1.1.4附录2大前端开发', link: '/7.网络应用开发/7.1.1.4附录2大前端开发' },
{ text: '7.1.1.5附录3跨端开发', link: '/7.网络应用开发/7.1.1.5附录3跨端开发' },
]
},
{
text: '7.1.2后端部分',
collapsed: true,
items: [
{ text: '7.1.2后端部分', link: '/7.网络应用开发/7.1.2后端部分' },
{ text: '7.1.2.1基础部分', link: '/7.网络应用开发/7.1.2.1基础部分' },
{ text: '7.1.2.2进阶部分', link: '/7.网络应用开发/7.1.2.2进阶部分' },
]
},
]
},
]
},
{
text: '8.基础学科',
collapsed: true,
items: [
{ text: '8.基础学科', link: '/8.基础学科/8.基础学科' },
{ text: '8.1经济学科普Part1', link: '/8.基础学科/8.1经济学科普Part1' },
]
},
{
text: 'Contributors',
link: '/contributors'
},
{
text: '贡献指南',
link: '/CONTRIBUTING'
},
{
text: 'notebook测试',
link: '/notebook'
}
],
outline: [2, 6],
socialLinks: [
{ icon: 'github', link: 'https://github.com/camera-2018/hdu-cs-wiki' }
],
footer: {
message: 'Made with ❤️ by HDU 计算机科协 && ALL 协作者',
copyright: 'Copyright © 2023-present Evan You && HDU 计算机科协 && ALL 协作者'
message: 'Made with ❤️ by ALL 协作者',
copyright: 'Copyright © 2023-present Evan You && ALL 协作者'
},
lastUpdatedText: '上次更改',
docFooter: {
@@ -679,16 +73,29 @@ export default defineConfig({
externalLinkIcon: true,
},
markdown: {
lineNumbers: true,
config: (md) => {
md.use(mathjax3);
},
},
vue: {
template: {
compilerOptions: {
isCustomElement: (tag) => customElements.includes(tag),
md.use(PanguPlugin);
},
math: true
},
sitemap: {
hostname: 'https://hdu-cs.wiki'
},
vite: {
plugins: [
VueMacros(),
],
resolve: {
alias: [
{
find: /^.*\/NotFound\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomNotFound.vue', import.meta.url)
)
}
]
}
}
})

27
.vitepress/nav.js Normal file
View File

@@ -0,0 +1,27 @@
export function nav() {
return [
{ text: '首页', link: '/' },
{
text: '章节', items:
[
{ text: '1.杭电生存指南(最重要模块)', link: '/1.杭电生存指南/1.1人文社科的重要性(韩健夫老师寄语)' },
{ text: '2.高效学习', link: '/2.高效学习/2.高效学习' },
{ text: '3.编程思维体系构建', link: '/3.编程思维体系构建/3.编程思维体系构建' },
{ text: '4.人工智能', link: '/4.人工智能/4.人工智能' },
{ text: '5.富有生命的嵌入式', link: '/5.富有生命的嵌入式/5.富有生命的嵌入式' },
{ text: '6.计算机安全', link: '/6.计算机安全/6.计算机安全' },
{ text: '7.网络应用开发', link: '/7.网络应用开发/7.网络应用开发入门' },
{ text: '8.基础学科', link: '/8.基础学科/8.基础学科' },
{ text: '9.计算机网络', link: '9.计算机网络/9.计算机网络' },
]
},
{ text: '博客', link: '/blog/' },
{ text: 'Wiki史', link: '/wiki史' },
{
text: '友链', items:
[
{ text: '杭电导航', link: 'https://wiki.hduhelp.com' },
]
},
]
}

692
.vitepress/sidebar.js Normal file
View File

@@ -0,0 +1,692 @@
export function main_sidebar() {
return [
{
text: '简介',
collapsed: true,
items: [
{ text: '简介', link: '/简介' },
{ text: '使用指南', link: '/使用指南' },
]
},
{
text: '1.杭电生存指南(最重要模块)',
collapsed: true,
items: [
{ text: '1.1 人文社科的重要性(韩健夫老师寄语)', link: '/1.杭电生存指南/1.1人文社科的重要性(韩健夫老师寄语)' },
{ text: '1.2 竞赛指北', link: '/1.杭电生存指南/1.2竞赛指北' },
{ text: '1.3 导师选择', link: '/1.杭电生存指南/1.3导师选择' },
{ text: '1.4 小心项目陷阱', link: '/1.杭电生存指南/1.4小心项目陷阱' },
{ text: '1.5 小组作业避雷指南', link: '/1.杭电生存指南/1.5小组作业避雷指南' },
{ text: '1.6 正确解读GPA', link: '/1.杭电生存指南/1.6正确解读GPA' },
{ text: '1.7 杭电出国自救指南', link: '/1.杭电生存指南/1.7杭电出国自救指南' },
{ text: '1.8 转专业二三事', link: '/1.杭电生存指南/1.8转专业二三事' },
{ text: '1.9 问题专题:好想进入实验室', link: '/1.杭电生存指南/1.9问题专题:好想进入实验室' },
{ text: '1.10 如何读论文', link: '/1.杭电生存指南/1.10如何读论文' },
{ text: '1.11 陷入虚无主义?进来看看吧', link: '/1.杭电生存指南/1.11陷入虚无主义?进来看看吧' },
{ text: '1.12 选课原则与抢课技巧', link: '/1.杭电生存指南/1.12选课原则与抢课技巧' },
{ text: '1.13 数学学习篇', link: '/1.杭电生存指南/1.13数学学习篇' },
{ text: '1.14 杭电“失败”指南', link: '/1.杭电生存指南/1.14 杭电失败指南' },
]
},
{
text: "2.高效学习",
collapsed: true,
items: [{ text: "2.高效学习", link: "/2.高效学习/2.高效学习" }]
},
{
text: "3.编程思维体系构建",
collapsed: true,
items: [
{ text: "3.编程思维体系构建", link: "/3.编程思维体系构建/3.编程思维体系构建" }
]
},
{
text: "4.人工智能",
collapsed: true,
items: [{ text: "4.人工智能", link: "/4.人工智能/4.人工智能" }]
},
{
text: "5.富有生命的嵌入式",
collapsed: true,
items: [
{ text: "5.富有生命的嵌入式", link: "/5.富有生命的嵌入式/5.富有生命的嵌入式" }
]
},
{
text: "6.计算机安全",
collapsed: true,
items: [{ text: "6.计算机安全", link: "/6.计算机安全/6.计算机安全" }]
},
{
text: "7.网络应用开发入门",
collapsed: true,
items: [
{ text: "7.网络应用开发入门", link: "/7.网络应用开发/7.网络应用开发入门" }
]
},
{
text: "8.基础学科",
collapsed: true,
items: [{ text: "8.基础学科", link: "/8.基础学科/8.基础学科" }]
},
{
text: "9.计算机网络",
collapsed: true,
items: [{ text: "9.计算机网络", link: "/9.计算机网络/9.计算机网络" }]
},
{
text: 'Contributors',
link: '/contributors'
},
{
text: '贡献指南',
link: '/CONTRIBUTING'
},
{
text: 'notebook测试',
link: '/notebook'
}
]
}
export function chapter2() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '2.高效学习',
collapsed: false,
items: [
{ text: '2.高效学习', link: '/2.高效学习/2.高效学习' },
{
text: '2.1高效的前提:摆脱高中思维',
collapsed: true,
items: [
{ text: '2.1高效的前提:摆脱高中思维', link: '/2.高效学习/2.1高效的前提:摆脱高中思维' },
{ text: '2.1.1悲壮的学习方式', link: '/2.高效学习/2.1.1悲壮的学习方式' },
{ text: '2.1.2浮躁的心理状态', link: '/2.高效学习/2.1.2浮躁的心理状态' },
{ text: '2.1.3错误的提问姿态', link: '/2.高效学习/2.1.3错误的提问姿态' },
{ text: '2.1.4书籍的盲目崇拜', link: '/2.高效学习/2.1.4书籍的盲目崇拜' },
{ text: '2.1.5错误的学习配比', link: '/2.高效学习/2.1.5错误的学习配比' },
]
},
{ text: '2.2优雅的使用工具', link: '/2.高效学习/2.2优雅的使用工具' },
{
text: '2.3高效的信息检索',
collapsed: true,
items: [
{ text: '2.3高效的信息检索', link: '/2.高效学习/2.3高效的信息检索' },
{ text: '2.3.1阅读文档B百度爬', link: '/2.高效学习/2.3.1阅读文档B百度爬' },
{ text: '2.3.2检索论文核心内容', link: '/2.高效学习/2.3.2检索论文核心内容' },
{ text: '2.3.3优秀的开源社区', link: '/2.高效学习/2.3.3优秀的开源社区' },
{ text: '补充:为什么不要用百度', link: '/2.高效学习/补充:为什么不要用百度' },
]
},
{ text: '2.4优雅的记笔记', link: '/2.高效学习/2.4优雅的记笔记' },
{ text: '2.5以理工科的方式阅读英语', link: '/2.高效学习/2.5以理工科的方式阅读英语' },
{ text: '2.6学会使用AI辅助学习', link: '/2.高效学习/2.6学会使用AI辅助学习' },
]
},
]
}
export function chapter3() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '3.编程思维体系构建',
collapsed: false,
items: [
{ text: '3.编程思维体系构建', link: '/3.编程思维体系构建/3.编程思维体系构建' },
{ text: '3.0 编程入门之道', link: '/3.编程思维体系构建/3.0 编程入门之道' },
{ text: '3.1该使用哪个编辑器???', link: '/3.编程思维体系构建/3.1该使用哪个编辑器???' },
{
text: '3.2算法杂谈',
collapsed: true,
items: [
{ text: '3.2算法杂谈', link: '/3.编程思维体系构建/3.2算法杂谈' },
{ text: '3.2.1为什么要选择ACM——谈谈我与ACM', link: '/3.编程思维体系构建/3.2.1为什么要选择ACM——谈谈我与ACM' },
{ text: '3.2.2手把手教你学算法——如何使用OJOnline Judge', link: '/3.编程思维体系构建/3.2.2手把手教你学算法——如何使用OJOnline Judge' },
{ text: '3.2.3ACM 竞赛从入门到入坟', link: '/3.编程思维体系构建/3.2.3ACM 竞赛从入门到入坟' },
]
},
{ text: '3.3如何选择编程语言', link: '/3.编程思维体系构建/3.3如何选择编程语言' },
{
text: '3.4C语言',
collapsed: true,
items: [
{ text: '3.4C语言', link: '/3.编程思维体系构建/3.4C语言' },
{ text: '3.4.1FAQ:常见问题', link: '/3.编程思维体系构建/3.4.1FAQ:常见问题' },
{ text: '3.4.2用什么写 C 语言', link: '/3.编程思维体系构建/3.4.2用什么写 C 语言' },
{ text: '3.4.3解决编程问题的普适性过程', link: '/3.编程思维体系构建/3.4.3解决编程问题的普适性过程' },
{ text: '3.4.4C语言前置概念学习', link: '/3.编程思维体系构建/3.4.4C语言前置概念学习' },
{
text: '3.4.5阶段一:编程属性',
collapsed: true,
items: [
{ text: '3.4.5阶段一:编程属性', link: '/3.编程思维体系构建/3.4.5阶段一:编程属性' },
{ text: '3.4.5.1C语言自测标准——链表', link: '/3.编程思维体系构建/3.4.5.1C语言自测标准——链表' },
]
},
{
text: '3.4.6阶段二文字冒险cool',
collapsed: true,
items: [
{ text: '3.4.6阶段二文字冒险cool', link: '/3.编程思维体系构建/3.4.6阶段二文字冒险cool' },
{ text: '3.4.6.1.开始冒险', link: '/3.编程思维体系构建/3.4.6.1.开始冒险' },
{ text: '3.4.6.2.探索未知', link: '/3.编程思维体系构建/3.4.6.2.探索未知' },
{ text: '3.4.6.3.指明地点', link: '/3.编程思维体系构建/3.4.6.3.指明地点' },
{ text: '3.4.6.4.创建对象', link: '/3.编程思维体系构建/3.4.6.4.创建对象' },
{ text: '3.4.6.5.捡起物品', link: '/3.编程思维体系构建/3.4.6.5.捡起物品' },
{ text: '3.4.6.6.绘制地图', link: '/3.编程思维体系构建/3.4.6.6.绘制地图' },
{ text: '3.4.6.7.增大距离', link: '/3.编程思维体系构建/3.4.6.7.增大距离' },
{ text: '3.4.6.8.移动方向', link: '/3.编程思维体系构建/3.4.6.8.移动方向' },
{ text: '3.4.6.9.练习:生成代码', link: '/3.编程思维体系构建/3.4.6.9.练习:生成代码' },
{ text: '3.4.6.10.增添属性', link: '/3.编程思维体系构建/3.4.6.10.增添属性' },
{ text: '3.4.6.11.设置条件', link: '/3.编程思维体系构建/3.4.6.11.设置条件' },
{ text: '3.4.6.12.开启关闭', link: '/3.编程思维体系构建/3.4.6.12.开启关闭' },
{ text: '3.4.6.13.编写解析器', link: '/3.编程思维体系构建/3.4.6.13.编写解析器' },
{ text: '3.4.6.14.丰富命令', link: '/3.编程思维体系构建/3.4.6.14.丰富命令' },
{ text: '3.4.6.15.赋予明暗', link: '/3.编程思维体系构建/3.4.6.15.赋予明暗' },
{ text: '3.4.6.16.结语:你终将自由', link: '/3.编程思维体系构建/3.4.6.16.结语:你终将自由' },
]
},
{
text: '3.4.7C基础知识杂谈',
collapsed: true,
items: [
{ text: '3.4.7C基础知识杂谈', link: '/3.编程思维体系构建/3.4.7C基础知识杂谈' },
{ text: '3.4.7.1GDB初探索(编程可阅览)', link: '/3.编程思维体系构建/3.4.7.1GDB初探索(编程可阅览)' },
{ text: '3.4.7.1.1调试理论', link: '/3.编程思维体系构建/3.4.7.1.1调试理论' },
{ text: '3.4.7.2C的历史问题undefined behavior', link: '/3.编程思维体系构建/3.4.7.2C的历史问题undefined behavior' },
{ text: '3.4.7.3C编译器干了什么', link: '/3.编程思维体系构建/3.4.7.3C编译器干了什么' },
{ text: '3.4.7.4Inline Assembly与链接加载', link: '/3.编程思维体系构建/3.4.7.4Inline Assembly与链接加载' },
]
},
]
},
{ text: '3.5git与github', link: '/3.编程思维体系构建/3.5git与github' },
{
text: '3.6Python(灵巧的胶水)',
collapsed: true,
items: [
{ text: '3.6Python(灵巧的胶水)', link: '/3.编程思维体系构建/3.6Python(灵巧的胶水)' },
{ text: '3.6.1从CS61A看编程语言学习', link: '/3.编程思维体系构建/3.6.1从CS61A看编程语言学习' },
{ text: '3.6.2环境配置', link: '/3.编程思维体系构建/3.6.2环境配置' },
{ text: '3.6.3安装python', link: '/3.编程思维体系构建/3.6.3安装python' },
{
text: '3.6.4Python for fun',
collapsed: true,
items: [
{ text: '3.6.4Python for fun', link: '/3.编程思维体系构建/3.6.4Python for fun' },
{ text: '3.6.4.0阶段零Python解释器', link: '/3.编程思维体系构建/3.6.4.0阶段零Python解释器' },
{ text: '3.6.4.1阶段一:熟悉语句', link: '/3.编程思维体系构建/3.6.4.1阶段一:熟悉语句' },
{ text: '3.6.4.2阶段二:递归操作', link: '/3.编程思维体系构建/3.6.4.2阶段二:递归操作' },
{ text: '3.6.4.3阶段三:数据抽象', link: '/3.编程思维体系构建/3.6.4.3阶段三:数据抽象' },
{ text: '3.6.4.4阶段四:高阶函数', link: '/3.编程思维体系构建/3.6.4.4阶段四:高阶函数' },
{ text: '3.6.4.5阶段五:迭代生成', link: '/3.编程思维体系构建/3.6.4.5阶段五:迭代生成' },
{ text: '3.6.4.6结语', link: '/3.编程思维体系构建/3.6.4.6结语' },
]
},
{
text: '3.6.5 CS61A 食用指南',
collapsed: true,
items: [
{ text: '3.6.5 CS61A 食用指南', link: '/3.编程思维体系构建/3.6.5CS61A食用指南' },
{ text: '3.6.5.1 CS61A Sec1', link: '/3.编程思维体系构建/3.6.5.1CS61A Sec1' },
]
}
]
},
{ text: '3.X 聊聊设计模式和程序设计', link: '/3.编程思维体系构建/3.X 聊聊设计模式和程序设计' },
{
text: '3.Y 附加模块Linux',
collapsed: true,
items: [
{ text: '3.Y 附加模块Linux', link: '/3.编程思维体系构建/3.Y 附加模块Linux' },
{ text: '3.Y.1Linux概念普及', link: '/3.编程思维体系构建/3.Y.1Linux概念普及' },
{ text: '3.Y.2双系统安装和发行版推荐', link: '/3.编程思维体系构建/3.Y.2双系统安装和发行版推荐' },
{ text: '3.Y.3VMware的安装与安装Ubuntu22.04系统', link: '/3.编程思维体系构建/3.Y.3VMware的安装与安装Ubuntu22.04系统' },
{ text: '3.Y.4WSL的安装', link: '/3.编程思维体系构建/3.Y.4WSL的安装' },
{ text: '3.Y.5Linux初探索', link: '/3.编程思维体系构建/3.Y.5Linux初探索' },
{ text: '3.Y.6Vim初探索', link: '/3.编程思维体系构建/3.Y.6Vim初探索' },
{ text: '3.Y.7linux小任务', link: '/3.编程思维体系构建/3.Y.7linux小任务' },
]
}
]
},
]
}
export function chapter4() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '4.人工智能',
collapsed: false,
items: [
{ text: '4.人工智能', link: '/4.人工智能/4.人工智能' },
{ text: '4.1前言', link: '/4.人工智能/4.1前言' },
{ text: '4.2机器学习AI快速入门quick start', link: '/4.人工智能/4.2机器学习AI快速入门quick start' },
{
text: '4.3人工智能导论及机器学习入门',
collapsed: true,
items: [
{ text: '4.3人工智能导论及机器学习入门', link: '/4.人工智能/4.3人工智能导论及机器学习入门' },
{
text: '4.3.1搜索',
collapsed: true,
items: [
{ text: '4.3.1搜索', link: '/4.人工智能/4.3.1搜索' },
{ text: '4.3.1.1程序示例——maze迷宫解搜索', link: '/4.人工智能/4.3.1.1程序示例——maze迷宫解搜索' },
{ text: '4.3.1.2项目Tic-Tac-Toe井字棋', link: '/4.人工智能/4.3.1.2项目Tic-Tac-Toe井字棋' },
]
},
{
text: '4.3.2知识推理',
collapsed: true,
items: [
{ text: '4.3.2知识推理', link: '/4.人工智能/4.3.2知识推理' },
{ text: '4.3.2.1程序示例——命题逻辑与模型检测', link: '/4.人工智能/4.3.2.1程序示例——命题逻辑与模型检测' },
{ text: '4.3.2.2项目:扫雷,骑士与流氓问题', link: '/4.人工智能/4.3.2.2项目:扫雷,骑士与流氓问题' },
]
},
{
text: '4.3.3不确定性问题',
collapsed: true,
items: [
{ text: '4.3.3不确定性问题', link: '/4.人工智能/4.3.3不确定性问题' },
{ text: '4.3.3.1程序示例', link: '/4.人工智能/4.3.3.1程序示例' },
{ text: '4.3.3.2项目:遗传', link: '/4.人工智能/4.3.3.2项目:遗传' },
]
},
{
text: '4.3.4最优化',
collapsed: true,
items: [
{ text: '4.3.4最优化', link: '/4.人工智能/4.3.4最优化' },
{ text: '4.3.4.1程序示例', link: '/4.人工智能/4.3.4.1程序示例' },
{ text: '4.3.4.2项目:填词游戏', link: '/4.人工智能/4.3.4.2项目:填词游戏' },
]
},
]
},
{ text: '4.4FAQ:常见问题', link: '/4.人工智能/4.4FAQ:常见问题' },
{
text: '4.6深度学习',
collapsed: true,
items: [
{ text: '4.6深度学习', link: '/4.人工智能/4.6深度学习' },
{ text: '4.6.1工欲善其事,必先利其器', link: '/4.人工智能/4.6.1工欲善其事,必先利其器' },
{ text: '4.6.2你可能会需要的术语介绍', link: '/4.人工智能/4.6.2你可能会需要的术语介绍' },
{ text: '4.6.3深度学习快速入门', link: '/4.人工智能/4.6.3深度学习快速入门' },
{ text: '4.6.4Pytorch安装', link: '/4.人工智能/4.6.4Pytorch安装' },
{
text: '4.6.5计算机视觉CV',
collapsed: true,
items: [
{ text: '4.6.5计算机视觉CV', link: '/4.人工智能/4.6.5计算机视觉CV' },
{ text: '4.6.5.1CV领域任务(研究目标)', link: '/4.人工智能/4.6.5.1CV领域任务(研究目标)' },
{
text: '4.6.5.2CV中的数据预处理torchvision',
collapsed: true,
items: [
{ text: '4.6.5.2CV中的数据预处理torchvision', link: '/4.人工智能/4.6.5.2CV中的数据预处理torchvision' },
{ text: '4.6.5.2.1数据读取', link: '/4.人工智能/4.6.5.2.1数据读取' },
{ text: '4.6.5.2.2数据增强', link: '/4.人工智能/4.6.5.2.2数据增强' },
]
},
{
text: '4.6.5.3CV中的经典网络',
collapsed: true,
items: [
{ text: '4.6.5.3CV中的经典网络', link: '/4.人工智能/4.6.5.3CV中的经典网络' },
{ text: '4.6.5.3.1AlexNet', link: '/4.人工智能/4.6.5.3.1AlexNet' },
{ text: '4.6.5.3.2FCN', link: '/4.人工智能/4.6.5.3.2FCN' },
{ text: '4.6.5.3.3ResNet', link: '/4.人工智能/4.6.5.3.3ResNet' },
{ text: '4.6.5.3.4UNet', link: '/4.人工智能/4.6.5.3.4UNet' },
{ text: '4.6.5.3.5GAN', link: '/4.人工智能/4.6.5.3.5GAN' },
{ text: '4.6.5.3.6思考题参考', link: '/4.人工智能/4.6.5.3.6思考题参考' },
{ text: '4.6.5.3.7还要学更多?', link: '/4.人工智能/4.6.5.3.7还要学更多?' },
]
},
{
text: '4.6.5.4神经辐射场(NeRF)',
collapsed: true,
items: [
{ text: '4.6.5.4神经辐射场(NeRF)', link: '/4.人工智能/4.6.5.4神经辐射场(NeRF)' },
{ text: '4.6.5.4.1NeRF', link: '/4.人工智能/4.6.5.4.1NeRF' },
{ text: '4.6.5.4.2NeRF的改进方向', link: '/4.人工智能/4.6.5.4.2NeRF的改进方向' },
{ text: '4.6.5.4.3自制数据集的工具COLMAP', link: '/4.人工智能/4.6.5.4.3自制数据集的工具COLMAP' },
]
},
{
text: '4.6.5.5行人重识别(ReID)',
collapsed: true,
items: [
{ text: '4.6.5.5行人重识别(ReID)', link: '/4.人工智能/4.6.5.5行人重识别(ReID)' },
]
},
]
},
{
text: '4.6.6自然语言处理NLP',
collapsed: true,
items: [
{ text: '4.6.6自然语言处理NLP', link: '/4.人工智能/4.6.6自然语言处理NLP' },
{ text: '4.6.6.1NLP领域任务(研究目标)', link: '/4.人工智能/4.6.6.1NLP领域任务(研究目标)' },
{
text: '4.6.6.2推荐系统',
collapsed: true,
items: [
{ text: '4.6.6.2推荐系统', link: '/4.人工智能/4.6.6.2推荐系统' },
{ text: '4.6.6.2.1推荐系统经典模型综述', link: '/4.人工智能/4.6.6.2.1推荐系统经典模型综述' },
{
text: '4.6.6.2.2基于数据的角度,看待推荐系统的构造',
collapsed: true,
items: [
{ text: '4.6.6.2.2基于数据的角度,看待推荐系统的构造', link: '/4.人工智能/4.6.6.2.2基于数据的角度,看待推荐系统的构造' },
{ text: '4.6.6.2.2.1《推荐系统实践》读后的一些想法', link: '/4.人工智能/4.6.6.2.2.1《推荐系统实践》读后的一些想法' },
{ text: '4.6.6.2.2.2推荐系统概念解释 and 一个好的推荐系统', link: '/4.人工智能/4.6.6.2.2.2推荐系统概念解释 and 一个好的推荐系统' },
{ text: '4.6.6.2.2.3推荐系统实例', link: '/4.人工智能/4.6.6.2.2.3推荐系统实例' },
{ text: '4.6.6.2.2.4利用用户行为数据', link: '/4.人工智能/4.6.6.2.2.4利用用户行为数据' },
{ text: '4.6.6.2.2.5推荐系统冷启动', link: '/4.人工智能/4.6.6.2.2.5推荐系统冷启动' },
{ text: '4.6.6.2.2.6利用标签信息', link: '/4.人工智能/4.6.6.2.2.6利用标签信息' },
{ text: '4.6.6.2.2.7利用上下文信息', link: '/4.人工智能/4.6.6.2.2.7利用上下文信息' },
]
},
{ text: '4.6.6.2.3序列化推荐', link: '/4.人工智能/4.6.6.2.3序列化推荐' },
]
},
{ text: '4.6.6.3知识图谱', link: '/4.人工智能/4.6.6.3知识图谱' },
]
},
{
text: '4.6.7Transformer',
collapsed: true,
items: [
{ text: '4.6.7Transformer', link: '/4.人工智能/4.6.7Transformer' },
{ text: '4.6.7.1VIT', link: '/4.人工智能/4.6.7.1VIT' },
{ text: '4.6.7.2BERT', link: '/4.人工智能/4.6.7.2BERT' },
{ text: '4.6.7.3MAE', link: '/4.人工智能/4.6.7.3MAE' },
]
},
{
text: '4.6.8对比学习',
collapsed: true,
items: [
{ text: '4.6.8对比学习', link: '/4.人工智能/4.6.8对比学习' },
{ text: '4.6.8.1前言', link: '/4.人工智能/4.6.8.1前言' },
{ text: '4.6.8.2Inst Disc', link: '/4.人工智能/4.6.8.2Inst Disc' },
{ text: '4.6.8.3定义正负样本的方式', link: '/4.人工智能/4.6.8.3定义正负样本的方式' },
{ text: '4.6.8.4MoCo', link: '/4.人工智能/4.6.8.4MoCo' },
{ text: '4.6.8.5SimCLR', link: '/4.人工智能/4.6.8.5SimCLR' },
{ text: '4.6.8.6SwAV', link: '/4.人工智能/4.6.8.6SwAV' },
{ text: '4.6.8.7BYOL', link: '/4.人工智能/4.6.8.7BYOL' },
{ text: '4.6.8.8SimSiam', link: '/4.人工智能/4.6.8.8SimSiam' },
{ text: '4.6.8.9MoCo v3', link: '/4.人工智能/4.6.8.9MoCo v3' },
{ text: '4.6.8.10总结', link: '/4.人工智能/4.6.8.10总结' },
]
},
{
text: '4.6.9深度强化学习',
collapsed: true,
items: [
{ text: '4.6.9深度强化学习', link: '/4.人工智能/4.6.9深度强化学习' },
{ text: '4.6.9.1前言', link: '/4.人工智能/4.6.9.1前言' },
{ text: '4.6.9.2基础资料推荐', link: '/4.人工智能/4.6.9.2基础资料推荐' },
{ text: '4.6.9.3基本概念介绍', link: '/4.人工智能/4.6.9.3基本概念介绍' },
]
}
]
},
{ text: '4.7图网络略述intro&GCN', link: '/4.人工智能/4.7图网络略述intro&GCN' },
{ text: '4.8数据分析', link: '/4.人工智能/4.8数据分析' },
{ text: '4.9如何做研究', link: '/4.人工智能/4.9如何做研究' },
{ text: '4.10科研论文写作', link: '/4.人工智能/4.10科研论文写作' },
{ text: '4.11从 AI 到 智能系统 —— 从 LLMs 到 Agents', link: '/4.人工智能/4.11从 AI 到 智能系统 —— 从 LLMs 到 Agents' },
{ text: '4.12LLM Agent之结构化输出', link: '/4.人工智能/4.12LLMAgent之结构化输出' },
{ text: '4.13本章节内容的局限性', link: '/4.人工智能/4.13本章节内容的局限性' },
{ text: 'SRT社团介绍', link: '/4.人工智能/SRT' },
{
text: 'FunRec',
collapsed: true,
items: [
{ text: 'FunRec概述', link: '/4.人工智能/FunRec概述' },
{
text: '推荐系统概述',
collapsed: true,
items: [
{ text: '推荐系统的意义', link: '/4.人工智能/ch01/ch1.1.md' },
{ text: '推荐系统架构', link: '/4.人工智能/ch01/ch1.2.md' },
{ text: '推荐系统技术栈', link: '/4.人工智能/ch01/ch1.3.md' },
]
},
{
text: '推荐系统算法基础',
collapsed: true,
items: [
{
text: '经典召回模型',
collapsed: true,
items: [
{
text: '基于协同过滤的召回', collapsed: true, items: [
{ text: 'UserCF', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/usercf.md' },
{ text: 'ItemCF', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/itemcf.md' },
{ text: 'Swing', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/Swing.md' },
{ text: '矩阵分解', link: '/4.人工智能/ch02/ch2.1/ch2.1.1/mf.md' },
]
},
{ text: 'FM召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/FM.md' },
{
text: 'item2vec召回系列', collapsed: true, items: [
{ text: 'word2vec原理', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/word2vec.md' },
{ text: 'item2vec召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/item2vec.md' },
{ text: 'Airbnb召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/Airbnb.md' },
]
},
{ text: 'YoutubeDNN召回', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/YoutubeDNN.md' },
{
text: '双塔召回', collapsed: true, items: [
{ text: '经典双塔', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/DSSM.md' },
{ text: 'Youtube双塔', link: '/4.人工智能/ch02/ch2.1/ch2.1.2/YoutubeTwoTower.md' },
]
},
{
text: '图召回', collapsed: true, items: [
{ text: 'EGES', link: '/4.人工智能/ch02/ch2.1/ch2.1.3/EGES.md' },
{ text: 'PinSAGE', link: '/4.人工智能/ch02/ch2.1/ch2.1.3/PinSage.md' },
]
},
{
text: '序列召回', collapsed: true, items: [
{ text: 'MIND', link: '/4.人工智能/ch02/ch2.1/ch2.1.4/MIND.md' },
{ text: 'SDM', link: '/4.人工智能/ch02/ch2.1/ch2.1.4/SDM.md' },
]
},
{
text: '树模型召回', collapsed: true, items: [
{ text: 'TDM', link: '/4.人工智能/ch02/ch2.1/ch2.1.5/TDM.md' },
]
}
]
},
{
text: '经典排序模型',
collapsed: true,
items: [
{ text: 'GBDT+LR', link: '/4.人工智能/ch02/ch2.2/ch2.2.1.md' },
{
text: '特征交叉', collapsed: true, items: [
{ text: 'FM', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/FM.md' },
{ text: 'PNN', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/PNN.md' },
{ text: 'DCN', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/DCN.md' },
{ text: 'AutoInt', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/AutoInt.md' },
{ text: 'FiBiNET', link: '/4.人工智能/ch02/ch2.2/ch2.2.2/FiBiNet.md' },
]
},
{
text: 'WideNDeep系列', collapsed: true, items: [
{ text: 'Wide&Deep', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/WideNDeep.md' },
{ text: 'NFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/NFM.md' },
{ text: 'AFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/AFM.md' },
{ text: 'DeepFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/DeepFM.md' },
{ text: 'xDeepFM', link: '/4.人工智能/ch02/ch2.2/ch2.2.3/xDeepFM.md' },
]
},
{
text: '序列模型', collapsed: true, items: [
{ text: 'DIN', link: '/4.人工智能/ch02/ch2.2/ch2.2.4/DIN.md' },
{ text: 'DIEN', link: '/4.人工智能/ch02/ch2.2/ch2.2.4/DIEN.md' },
{ text: 'DSIN', link: '/4.人工智能/ch02/ch2.2/ch2.2.4/DSIN.md' },
]
},
{
text: '多任务学习', collapsed: true, items: [
{ text: '多任务学习概述', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/2.2.5.0.md' },
{ text: 'ESMM', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/ESMM.md' },
{ text: 'MMOE', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/MMOE.md' },
{ text: 'PLE', link: '/4.人工智能/ch02/ch2.2/ch2.2.5/PLE.md' },
]
}
]
}
]
}
]
}
]
},
]
}
export function chapter5() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '5.富有生命的嵌入式',
collapsed: false,
items: [
{ text: '5.富有生命的嵌入式', link: '/5.富有生命的嵌入式/5.富有生命的嵌入式' },
{ text: '5.1嵌入式是什么?可以吃吗?', link: '/5.富有生命的嵌入式/5.1嵌入式是什么?可以吃吗?' },
{ text: '5.2New meaning of C', link: '/5.富有生命的嵌入式/5.2New meaning of C' },
{ text: '5.3还玩裸机?上操作系统!', link: '/5.富有生命的嵌入式/5.3还玩裸机?上操作系统!' },
]
},
]
}
export function chapter6() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '6.计算机安全',
collapsed: false,
items: [
{ text: '6.计算机安全', link: '/6.计算机安全/6.计算机安全' },
{
text: '6.1Web安全',
collapsed: true,
items: [
{ text: '6.1Web安全', link: '/6.计算机安全/6.1Web安全' },
{ text: '6.1.1SQL 注入', link: '/6.计算机安全/6.1.1SQL 注入' },
]
},
{
text: '6.2二进制安全',
collapsed: true,
items: [
{ text: '6.2二进制安全', link: '/6.计算机安全/6.2二进制安全' },
{ text: '6.2.1基础工具的使用', link: '/6.计算机安全/6.2.1基础工具的使用' },
{ text: '6.2.2软件破解、软件加固', link: '/6.计算机安全/6.2.2软件破解、软件加固' },
{ text: '6.2.3漏洞挖掘、漏洞利用', link: '/6.计算机安全/6.2.3漏洞挖掘、漏洞利用' },
]
},
{ text: '6.3密码学', link: '/6.计算机安全/6.3密码学' },
{ text: '6.4安全杂项', link: '/6.计算机安全/6.4安全杂项' },
{ text: '6.5学习资料推荐', link: '/6.计算机安全/6.5学习资料推荐' },
]
},
]
}
export function chapter7() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '7.网络应用开发',
collapsed: false,
items: [
{ text: '7.网络应用开发入门', link: '/7.网络应用开发/7.网络应用开发入门' },
{
text: '7.1WEB开发入门',
collapsed: true,
items: [
{ text: '7.1WEB开发入门', link: '/7.网络应用开发/7.1WEB开发入门' },
{
text: '7.1.1前端部分',
collapsed: true,
items: [
{ text: '7.1.1前端部分', link: '/7.网络应用开发/7.1.1前端部分' },
{ text: '7.1.1.1基础部分', link: '/7.网络应用开发/7.1.1.1基础部分' },
{ text: '7.1.1.2进阶部分', link: '/7.网络应用开发/7.1.1.2进阶部分' },
{ text: '7.1.1.3附录1前端介绍详细版', link: '/7.网络应用开发/7.1.1.3附录1前端介绍详细版' },
{ text: '7.1.1.4附录2大前端开发', link: '/7.网络应用开发/7.1.1.4附录2大前端开发' },
{ text: '7.1.1.5附录3跨端开发', link: '/7.网络应用开发/7.1.1.5附录3跨端开发' },
]
},
{
text: '7.1.2后端部分',
collapsed: true,
items: [
{ text: '7.1.2后端部分', link: '/7.网络应用开发/7.1.2后端部分' },
{ text: '7.1.2.1基础部分', link: '/7.网络应用开发/7.1.2.1基础部分' },
{ text: '7.1.2.2进阶部分', link: '/7.网络应用开发/7.1.2.2进阶部分' },
]
},
]
},
]
},
]
}
export function chapter8() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '8.基础学科',
collapsed: false,
items: [
{ text: '8.基础学科', link: '/8.基础学科/8.基础学科' },
{ text: '8.1经济学科普Part1', link: '/8.基础学科/8.1经济学科普Part1' },
]
}
]
}
export function chapter9() {
return [
{ text: '返回上一层', link: '/简介' },
{
text: '9.计算机网络',
collapsed: false,
items: [
{ text: '9 计算机网络', link: '/9.计算机网络/9.计算机网络' },
{ text: '9.1 计网速通', link: '/9.计算机网络/9.1计网速通' },
{ text: '9.2.1 物理层' },
{ text: '9.2.2 链路层' },
{
text: '9.2.3 网络层',
collapsed: true,
items: [
{ text: '9.2.3 网络层', link: '/9.计算机网络/9.2.3网络层' },
{ text: '9.2.3.1 IP 协议', link: '/9.计算机网络/9.2.3.1IP协议' },
{ text: '9.2.3.2 子网与无类域间路由', link: '/9.计算机网络/9.2.3.2子网与无类域间路由' }
]
},
]
}
]
}

View File

@@ -0,0 +1,70 @@
<script setup>
import { useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { nextTick, provide } from 'vue'
const { isDark } = useData()
const enableTransitions = () =>
'startViewTransition' in document &&
window.matchMedia('(prefers-reduced-motion: no-preference)').matches
provide('toggle-appearance', async ({ clientX: x, clientY: y }) => {
if (!enableTransitions()) {
isDark.value = !isDark.value
return
}
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
)}px at ${x}px ${y}px)`
]
await document.startViewTransition(async () => {
isDark.value = !isDark.value
await nextTick()
}).ready
document.documentElement.animate(
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
{
duration: 300,
easing: 'ease-in',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
})
</script>
<template>
<DefaultTheme.Layout />
</template>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root),
.dark::view-transition-new(root) {
z-index: 1;
}
::view-transition-new(root),
.dark::view-transition-old(root) {
z-index: 9999;
}
.VPSwitchAppearance {
width: 22px !important;
}
.VPSwitchAppearance .check {
transform: none !important;
}
</style>

View File

@@ -2,28 +2,29 @@
import { h, watch } from 'vue'
// import Theme from 'vitepress/theme'
import DefaultTheme from 'vitepress/theme-without-fonts'
import Layout from './Layout.vue'
import Download from '../../components/Download.vue'
import Bilibili from '../../components/Bilibili.vue'
import Parallax from '../../components/Parallax.vue'
import './style.css'
import './rainbow.css'
let homePageStyle = undefined
export default {
...DefaultTheme,
Layout: () => {
return h(DefaultTheme.Layout, null, {
})
},
Layout: Layout,
enhanceApp(ctx) {
DefaultTheme.enhanceApp(ctx)
ctx.app.component('Download', Download)
ctx.app.component('Bilibili', Bilibili)
ctx.app.component('Parallax', Parallax)
if (typeof window === 'undefined')
return
watch(
() => ctx.router.route.data.relativePath,
() => updateHomePageStyle(location.pathname === '/' || location.pathname === '/contributors.html'),
() => updateHomePageStyle(location.pathname === '/' || location.pathname === '/contributors'),
{ immediate: true },
)
},

View File

@@ -2,23 +2,37 @@
* Customize default theme styling by overriding CSS variables:
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
*/
@import url('https://fonts.loli.net/css2?family=Noto+Color+Emoji&family=Noto+Sans+Mono:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;700&display=swap');
/**
* Colors
* -------------------------------------------------------------------------- */
@import url('https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&family=Noto+Sans+Mono:wght@400;600;700&family=Noto+Sans+SC:wght@400;600;700&display=swap');
.dark .vp-doc a,#loading, .dark .vp-doc a>code, .dark .VPNavBarMenuLink.VPNavBarMenuLink:hover, .dark .VPNavBarMenuLink.VPNavBarMenuLink.active, .dark .link.link:hover, .dark .link.link.active, .dark .edit-link-button.edit-link-button, .dark .pager-link .title {
color: var(--vp-c-brand-lighter);
color: var(--vp-c-brand-3);
}
/**
* 这个版本可能有 bugbuild 后字体变不了还为 consolas 可能是我自己配的有问题 可能是这个版本拉了 总之就加个临时的
* -------------------------------------------------------------------------- */
code {
font-family: 'Noto Sans Mono', sans-serif, monospace, consolas !important;
font-weight: 400 !important;
font-size: 14px !important;
}
:root {
--vp-c-brand: #0dadc4;
--vp-c-brand-light: #1A9CED;
--vp-c-brand-lighter: #1CA8FF;
--vp-c-brand-lightest: #5EB2E6;
--vp-c-brand-dark: #0B52BF;
--vp-c-brand-darker: #015F8F;
--vp-c-brand-dimm: rgba(100, 108, 255, 0.08);
--vp-c-brand-1: #0dadc4;
--vp-c-brand-2: #1A9CED;
--vp-c-brand-3: #1CA8FF;
--vp-c-brand-soft: #5EB2E6;
--vp-code-copy-copied-text-content: '复制成功';
--vp-code-color: rgba(60, 60, 67);
--vp-custom-block-tip-bg: rgba(100, 108, 255, 0.16) !important;
--vp-badge-tip-bg: rgba(100, 108, 255, 0.16) !important;
}
.dark {
--vp-code-color: rgba(255, 255, 245, 0.86);
}
:root {
@@ -31,15 +45,15 @@
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: var(--vp-c-brand-light);
--vp-button-brand-border: transparent;
--vp-button-brand-text: var(--vp-c-white);
--vp-button-brand-bg: var(--vp-c-brand);
--vp-button-brand-hover-border: var(--vp-c-brand-light);
--vp-button-brand-bg: var(--vp-c-brand-3);
--vp-button-brand-hover-border: transparent;
--vp-button-brand-hover-text: var(--vp-c-white);
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
--vp-button-brand-active-border: var(--vp-c-brand-light);
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
--vp-button-brand-active-border: transparent;
--vp-button-brand-active-text: var(--vp-c-white);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
--vp-button-brand-active-bg: var(--vp-c-brand-1);
}
/**
@@ -81,15 +95,10 @@
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-darker);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
}
.dark {
--vp-custom-block-tip-border: var(--vp-c-brand);
--vp-custom-block-tip-text: var(--vp-c-brand-lightest);
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
--vp-custom-block-tip-border: transparent;
--vp-custom-block-tip-text: var(--vp-c-text-1);
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
}
/**
@@ -97,7 +106,7 @@
* -------------------------------------------------------------------------- */
.DocSearch {
--docsearch-primary-color: var(--vp-c-brand) !important;
--docsearch-primary-color: var(--vp-c-brand-1) !important;
}
mjx-container {
@@ -116,7 +125,6 @@ mjx-container {
opacity: 1;
}
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(
@@ -186,3 +194,11 @@ mjx-container {
-webkit-user-drag: none !important;
-moz-user-drag: none !important;
}
.custom-block.tip code {
background-color: rgba(100, 108, 255, 0.14);
}
mjx-container > svg {
display: inline-block;
}

View File

@@ -1,41 +0,0 @@
# 程序员如何活久一点
### 1. 术语
* ACM: All-Cause Mortality / 全因死亡率
### 2. 目标
* 稳健地活得更久
### 3. 关键结果
* 降低66.67%全因死亡率
* 增加\~20年预期寿命
* ~~维持多巴胺于中轴~~
### 4. 分析
* 主要参考对ACM的学术文献相对较多可以作为主要参考
* 增加寿命与ACM关系非线性显然增加寿命与ACM关系是非线性函数这里假设 `DeltaLifeSpan=(1/(1+DeltaACM)-1)*10`DeltaACM为ACM变化值公式欢迎优化
* 变量无法简单叠加:显然各个变量之间并不符合独立同分布假设,变量之间的实际影响也并不明确
* 存在矛盾观点:所有的证据都有文献/研究对应但注意到有些文献之间有显著矛盾的观点如对于碳水摄入比例的矛盾有些文献存在较大争议如认为22点前睡觉会提升43%全因死亡率)
* 研究仅表达相关:所有文献表明的更多是相关而非因果,在阅读时要考虑文献是否充分证明了因果 —— 如某文献表明了日均>=7000步的人有显著低的全因死亡率。但步数少的人可能包含更多长期病患如果没有合理的排除这块数据那此文献调查失真
### 5. 行动
* 输入
* 固体:吃白肉(-11%\~-3% ACM、蔬果为主-26%\~-17% ACM多吃辣-23% ACM多吃坚果-27%\~-4% ACM*少吃蛋黄(否则+7% ACM/0.5颗/天)(存在争议)*,中量碳水、多吃植物蛋白(-10% ACM少吃超加工食物-62%\~-18%
* 液体:喝咖啡(-22%\~-12% ACM喝牛奶-17%\~-10% ACM喝茶-15%\~-8% ACM少喝或不喝甜味饮料否则每天一杯+7% ACM+多巴胺戒酒或每周100g纯酒精量(g)=饮酒量(ml)×酒精浓度(%)×酒精密度0.8g/ml否则+\~50% ACM无上限
* 气体:不吸烟(否则+~50% ACM-12\~-11年寿命
* 光照:晒太阳(-~40% ACM
* 药物:二甲双胍(糖尿病人相比正常人可以+3年、复合维生素-8%癌症风险)、亚精胺(-60%\~-30% ACM、葡萄糖胺-39% ACM
* 输出
* 运动每周3次45分钟挥拍运动-47% ACM
* 日常:刷牙(-25% ACM
* 睡眠每天睡7小时全因死亡率最低且22-24点间最好*早睡+43% ACM晚睡+15% ACM存在争议*
* 上下文
* 体重:减肥(-54% ACM
::: tip 🧑‍🍳
全文 [程序员延寿指南 | A programmer's guide to live longer](https://github.com/geekan/HowToLiveLonger)
:::

View File

@@ -2,32 +2,42 @@
> author: ek1ng
>
> 本文编写自2021.07.31,也许有些内容已经过时,请选择性参考。
> 本文编写自 2021.07.31,也许有些内容已经过时,请选择性参考。
## 选课原则
### 要选哪些课
在杭电,学生必须修读完培养计划上所有的课程才能够毕业,因此选课遵循的唯一纲要便是培养计划,一切以培养计划上的要求为准,体育课、通识必修课、通识选修课、专业选修课、专业必修课等等,请注意任何选课尽可能请以培养计划的课程代码为准,若课程代码不同则需要通过课程替代等方式。
### 为什么要选课
选课其实是选老师,而选择的选课老师的背后则是课程考核方式、给分高低、成绩占比、课堂签到情况等等。选择正确的老师能够使课堂更加符合你的预期,不论是教学质量还是教学方式亦或期末分数上。
在讨论之前,必须声明一些学校课程的基本要求,例如学校要求老师采取易班点名的方式,所以除了某些老师以外大多数老师都会采取不定次数的课堂点名以及点教室人头的方式作为考核考勤情况的方式。
### 学校开什么课
学校开展体育课大一大二4学期分别修读不同类别的体育课程4次、通识选修课 ~~通常各专业需要修读人文类、国际类、科技类学分4、4、2个~~
学校开展体育课(大一大二 4 学期分别修读不同类别的体育课程 4 次)、通识选修课 ~~(通常各专业需要修读人文类、国际类、科技类学分 4、4、2 个)~~
:::warning
2023年更新现在是国际类、人文类、艺术类、科技类学分4、2、2、2个不管怎么变应该加起来都是10分
2023 年更新:现在是国际类、人文类、艺术类、科技类学分 4、2、2、2 个(不管怎么变应该加起来都是 10 分)
:::
### 选什么课好
在杭电换客群或者与认识的室友、同学、朋友等等交流开展某课程的某老师教学情况打听情报以选择合适的老师。此处的情报通常指老师的教学方式如何采取怎样的签到方式等等。如果曾经上过某老师开展的a课程那么通常对于他开展的b课程签到情况和给分情况都仍然能够适用但是教学情况则未必。
### 常见问题Q&A
在杭电换客群或者与认识的室友、同学、朋友等等交流开展某课程的某老师教学情况,打听情报以选择合适的老师。此处的情报通常指老师的教学方式如何,采取怎样的签到方式等等。如果曾经上过某老师开展的 a 课程,那么通常对于他开展的 b 课程,签到情况和给分情况都仍然能够适用,但是教学情况则未必。
### 常见问题 Q&A
Q1:我该如何安排我这一学期的课程?
A1:尽可能按照培养计划给出的每学期修读建议修读,适当先在大一、大二修读通识选修、体育课以及适量的专业必修专业选修,在大三修读更多的专业课程。当然如果完全打乱培养计划在杭电也是完全允许的,你完全可以在大一、大二修读大三的课程,在大三修读大一的课程,这么做的意义也许是你希望通过修读课程顺序的改变来调整你个人的时间安排,不论如何这是符合学校规章制度的操作,只要你想你就可以这么做。
Q2:选课所谓第一轮选课第二轮选课到底是如何进行的?
A2:第一轮选课可以选择的课为体育课、通识选修课(英语拓展课、大学军事、公选课都包括在内)、推荐课表上的课程。第二轮选课可以跨年级跨学院跨专业选课,只要能搜到的课都是可以上的,不过请注意,思修近代史毛概马原形策等课程并不能提前修读。第二轮选课通常进行到开学后3周,在开学前3可以通过签课的方式即在授课老师、学院的批准通过下选上自己没有抢到的课理论上任何课需要注意公选课、体育课一般无法签课老师是否同意签课通常看老师的个人情况学院通常会在老师批准的情况下通过批准只要经过批准都可以签课成功后出现在课表上。请注意学分上限为32.5不包括暑假短学期课程转专业后学分上限自动扩为40若非转专业学生可以在绩点3.0以上的情况下开学前3周内提出扩学分请求。
A2:第一轮选课可以选择的课为体育课、通识选修课(英语拓展课、大学军事、公选课都包括在内)、推荐课表上的课程。第二轮选课可以跨年级跨学院跨专业选课,只要能搜到的课都是可以上的,不过请注意,思修近代史毛概马原形策等课程并不能提前修读。第二轮选课通常进行到开学后 3 周,在开学前 3 周,可以通过签课的方式即在授课老师、学院的批准通过下选上自己没有抢到的课,理论上任何课(需要注意公选课、体育课一般无法签课,老师是否同意签课通常看老师的个人情况,学院通常会在老师批准的情况下通过批准)只要经过批准都可以签课成功后出现在课表上。请注意,学分上限为 32.5(不包括暑假短学期课程),转专业后学分上限自动扩为 40若非转专业学生可以在绩点 3.0 以上的情况下开学前 3 周内提出扩学分请求。
:::warning
2023年更新学分上限好像变高了但我忘了是多少🤡
Update: 新系统学分上限为 36扩学分后上限为 40。
:::
Q3大一上如何选课
@@ -35,20 +45,29 @@ Q3大一上如何选课
A3大一上选课的安排在最后时间段体育被默认选了太极拳并选不到“好”的公选课专业课等等不太建议选很多课选一门新生研讨课或者推荐不选课。
## 抢课技巧
### 选课背景
2021年上学期的选课中杭电更换了正方全新的选课平台http://newjw.hdu.edu.cn 目前选课平台的特性为在选课时间内开放至公网ip可以访问可以并发请求~~并不会网页卡崩~~,抢课全靠手速。
2021 年上学期的选课中,杭电更换了正方全新的选课平台 <http://newjw.hdu.edu.cn>,目前选课平台的特性为,在选课时间内开放至公网 ip 可以访问,可以并发请求,~~并不会网页卡崩~~,抢课全靠手速。
:::tip
1. 鉴于杭电复杂的网络环境,在**内网**抢课甚至不如**公网**😅,所以建议在寝室里连上网线(公网)抢课。
鉴于杭电复杂的网络环境,在**内网**抢课甚至不如**公网**😅,所以建议在寝室里连上网线(公网)抢课。
2. **网页会卡崩**刚开始选课0~5分钟系统会未响应甚至将你踢出登录还会让你浏览器爆掉显示 *欧呦,崩溃啦* 之类的字样,一切听天由命。
1. **网页会卡崩**,刚开始选课 0~5 分钟系统会未响应甚至将你踢出登录,还会让你浏览器爆掉显示 *欧呦,崩溃啦* 之类的字样,一切听天由命。
:::
## 具体技巧
#### 系统开放前
通常系统开放前可以查询开课情况,那么可以根据开课情况自己提前规划安排想上的课程。
#### 系统开放时
##### 第一轮选课、第二轮选课开放系统时
## 具体技巧
### 系统开放前
通常系统开放前可以查询开课情况,那么可以根据开课情况自己提前规划安排想上的课程。
### 系统开放时
#### 第一轮选课、第二轮选课开放系统时
提前在粘贴板中剪切/复制第一手要抢的课程,并且在选课平台开放时间前几秒,不停点击刷新,直至选课平台显示的内容不为非选课时间而是可以搜索,粘贴课程名并且点击抢课即可第一手抢到最想抢的课程,再依次抢接下来准备上的课。若课表上已经被系统默认选的课占了想要选的课的位置,那么就需要先退课再选课。
##### 假期以及开学前三周
#### 假期以及开学前三周
这时候会有同学因为不想选某门课程或者通过将课卡在其他人号上想在假期“转移”到自己号上,选课系统中的课程余量就会时不时出现波动,此时可以上去系统看看说不定能捡漏哦。签课以及扩学分在开学前三周进行,请关注学校通知并且通过签课选上自己没能选上的课程。

View File

@@ -0,0 +1,263 @@
# 数学学习篇
> author张晓鹏
>
> 本文章仅为导引
## 认知部分
其实之前这一部分写了一大堆,但感觉文字实在是太太太多了,又觉得这种认知篇应该在生存指南部分,因此重新修改了一个相对精简版,希望读者能理解我的意思,也容忍我的啰嗦。(实际上还是很多啊啊啊啊)
在开始正式这一篇章前,我们需要先闲聊几句,这几句无关你的学习,但又可能无时无刻与你的学习相关。
1. 互联网时代下,学习资源过分的多,但学习资源的**质量参差不齐**。
- 啰嗦一:国内的教培太过魔怔,各种速成课、考研课,这种总结式的,反刍式的学习资源,在前期学习是极其不推荐的,它很可能会限制你的思维。
- 啰嗦二:很多课程不是为你电定制的,你电虽然不算特别好的学校,但也不算差的,按照我老师的说法,根据当年精英教育比例来看,我们虽然算垫底,但还是精英教育。互联网上有非常非常多的课程是为了二三本同学,播放量高也是如此,毕竟市场人数差很大啊!
2. 资源的**好坏定义取决于你自身的适配度**,适配度越高越好,并不是难度越高越好。
- 解释:他人认为的极好的书籍或课程,对他来说适配度 100%,对你来说却可能是 0%,因为你可能完全学不懂,或者对你而言,其学习过程完全没有兴趣。
3. 时间是极其稀贵的物品,不要浪费你的时间!
- 解释:对于大部分工科学生来说,**数学更多是工具**,需要的是数学应用,而不是像数学系同学一样,理解数学的理论。诚然,能深刻理解数学,是能更好的利用工具,甚至创造工具,但是时间成本太高,大部分情况下性价比过低。
- 有人会说:专业学到很深的时候,后面会涉及大量数学理论,因此他要前期打下极其扎实的数学基础。
- 笔者的回复是:你不是小说男主,你不需要一开始就选择逆天功法,踏踏实实的努力足以支撑你的小世界。如果为了后续极高的上限,而在前期花费过多时间,其一,你很可能在应用层面被同龄人甩远而承受打击;其二,你很可能学了一堆其他领域侧重的数学理论,这在你实际专业和工作中可能完全用不到;其三,数学学不完的,他不像高中有考纲,有穷尽。
4. 高效利用时间的前提就是**明确自我需求**,针对需求进行**合理取舍**,建议设计一个尽可能适合自己的学习计划,过程中可以询问学长学姐一些建议,但仅是建议,最终决定权在你!
- 解释:比如你未来的梦想工作是算法工程师,那么你在对应算法领域的数学要多尝试些,而其他部分可以省略些;如果你的未来工作和数学没有关系!那么别学了(开个玩笑,但是要求就变成了能过就行)!
- 啰嗦:学长学姐仅比你早一些来到学校,与你也没有责任与义务,其所表达观点也不一定对的,甚至大部分情况下,很多人的观念就是很被动的,千万千万不要被限制了,请主动思考什么是合适你的,什么是你想要的!
5. 学习资源不代表视频资源,公共性课程视频资源很多,但随着专业深入,视频会越来越少,书籍和文献会成为主要学习路径,特别是外文文献。因此在能继续学习的前提下,**多尝试直接啃书**,而不是看视频。
- 啰嗦:国内的一些论文和书籍真的是依托答辩!原因没法告诉,这是不能碰的滑梯,但理工科文献尽可能就别看国内的了,说不定里面就有错误,然后影响你很久!(不代表国外就没错误,但是国内的这个整体问题比例太离谱了)
6. 相信国外热门的资源都会有本土化,但是本土化的水平可能参差不齐,当自己**过于难理解时****请看一下英文原著**,因为可能问题不在于你,而在于翻译。
- 啰嗦:有些书籍的翻译是依托答辩!甚至题目都会给你抄错!
7. **不要拒绝英文**,尝试拥抱,即便这看起来很困难,但慢慢会好起来的。(这与你的高考英语一点关系没有,别担心,你可以的!)
8. 国内和国外的教材区别比较大,有一个恰当又不恰当的比喻:**国内的多数教材就像讲义**,看似清清楚楚,实则云里雾里,需要老师来带才能理解;**国外的经典教材如同仙人指路**,带你拨开迷雾。
- 啰嗦:这里并不代表国外就好,国内就差,前提也是国外经典教材,其次国情不同,国内中学阶段都是阅读讲义,因此大学这样编写也是正常的,默认需要老师来讲。(即便笔者觉得这很不合适)
## 推荐学习线路篇
### 高等数学
#### 整体框架介绍
这里我对高等数学做一些简单的个人视角的介绍
其实高等数学/微积分,**全篇内容都在讲极限**,而这也是大学数学与高中数学最大的不同,高等数学的一切都**建立于无穷之上**,而极限是无穷的一种极好的表达方式。如果你在学习的过程中,全篇以极限的角度去审视这些内容,你就会发现,这里面所有的运算都是极限运算,包括导数、积分,甚至级数部分,前期可能感受不深,越到后面越发会感受到,一切的运算都是极限运算,那些所谓的性质和一些不能使用的特殊情况,往往也都来源于这个最本质的家伙,极限!就这样,是不是感觉讲了没讲,没错,还真是!因为数学太深了,再细节下去就不是一篇文章所讲的完了。还想知道更多吗?那就去看下面的**3Blue1Brown 的微积分本质**
下面到这个文章没啥意思的推荐部分了。不过还是强调一句:**根据你的需求进行选择**
#### 系统性的网课推荐
这里没有放速成课和考研课,因为笔者认为这两类课程的功利性过强,并且对知识的总结过多,不利于未来深入学习其他内容,因此不算传统学习路线,将速成课放在了最后应试技巧部分(考研课没推荐,因为笔者是数学系同学,这些不清楚,是一点也没看过)
个人推荐优先级(以难度和深度划分):上交大乐经良>国防科大版本>宋浩
风格上前两者更传统,内容也更系统深刻,个人更喜欢乐老师一些;第三个宋浩老师课堂相对更活跃些,会讲比较多的段子,难度也更低一些。
系统性的网课选其一能完整跟下来即可(跟不下来也正常,坚持挺难的)
如果你只是为了考试,选择宋浩版本就足够了;如果为了未来工作,工程应用方面会涉及比较多,请选择前两个更系统的课程。如果觉得这些不合适,那么可以自行搜索选择其他课程。
##### 《高等数学》上交大乐经良老师
- 链接:[【高等数学 - 上海交通大学 - 乐经良老师 高清修复 1080p全集](https://www.bilibili.com/video/BV1aY4y137fr/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1aY4y137fr'/>
##### 国防科大《高等数学》
- 链接:[【国防科大高等数学【全网最佳】](https://www.bilibili.com/video/BV1F7411B7ep/?p=291&share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1F7411B7ep'/>
##### 宋浩《高等数学》
- 链接:[【《高等数学》同济版 全程教学视频(宋浩老师)】](https://www.bilibili.com/video/BV1Eb411u7Fw/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1Eb411u7Fw'/>
##### 《微积分》苏德矿
这个版本比较特别,比较**偏向经管类**的同学,因此没有放在前面比较。
- 【[微积分(浙江大学 苏德矿/矿爷)】](https://www.bilibili.com/video/BV1Lt411r7NQ/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1Lt411r7NQ'/>
- 如果苏德矿老师版本不太能接受的话,请看宋浩老师版本的微积分,但需要注意的是**宋浩老师版本与杭电考试范围有所不同**,可能需要缺失部分补齐一下。
- 因为笔者对经管类数学了解远不如理工科数学,因此这里不做过多阐述,同学可以自行搜索了解。
#### 教材推荐
这一块相对简略一些,主要是几个点
1. 如果是自学,不推荐看同济版教材,和前面说的一样,那个像讲义,并且难度也不够,太浅了,需要老师来给你上课做额外注记。
2. 图灵系列的书籍都是很不错的,并且套系的书很多,具体的可以先不着急买,可以先自行搜索电子书(前面章节应该有教的)
3. 书单链接:[数学经典教材有什么? - 人民邮电出版社的回答 - 知乎](https://www.zhihu.com/question/22302252/answer/1733795665)
4. 自行选择,能读完一个本就足够了,而且读不完正常,根据以往经验的不科学推断,大部分人最多看完网课,书本草草翻过。
#### 辅助工具推荐
这部分内容与传统的网课不同,更倾向于**知识体系的辅助构建和补充**,某种程度上你可以认为是精华内容。
##### 3Blue1Brown 的微积分本质
这个名字听起来就很不错,对吧!
1. 链接:[3Blue1Brown 的个人空间_哔哩哔哩_bilibili](https://space.bilibili.com/88461692/channel/seriesdetail?sid=1528931)
2. 内容是英文的,但实际上不会怎么影响,若是过于难接受英文,可以自行搜索汉语翻译版。
3. 这部分内容和传统的高数教学不同,从直观的**图形角度**,讲解各个微积分中的重要概念由来和应用。
4. 学习时间:与传统网课无任何冲突,可以在**任何时间观看**,即传统网课的前、中、后三个阶段均可看,并且不同阶段看感受不同,**建议反复观看**。
5. 学习难度:简单又不简单,简单在于讲解的方式非常通俗,图形化知识非常直观,不简单在于其本身内容是深刻的,彻底理解这些内容或许需要不断反复的看以及配合传统网课的学习,搭建完知识体系后顿悟。
##### Brilliant
1. 链接:[https://brilliant.org/](https://brilliant.org/)。
2. 国外非常火的直观学习数学网站,国内本土化产物是马同学图解数学,个人不推荐购买马同学图解数学,因为据个人了解,里面错误似乎比较多,但可以看其知乎上的好文章。
3. 这个网站不做过多介绍,自己打开玩一玩就明白了。
4. 额外补充一这是一个付费内容前几天是免费的如果你觉得他值得可以进行购买购买途径可以官网但第三方价格会便宜些比如淘宝、闲鱼、PDD。
5. 额外补充二:一个好用的翻译浏览器插件:沉浸式翻译,可以更好的体验。
##### MIT-微积分重点
1. 链接:[【我在 B 站上大学!【完整版 - 麻省理工 - 微积分重点】全 18 讲学数学不看的微积分课程看完顺滑一整年。_人工智能数学基础/机器学习/微积分/麻省理工/高等数学】](https://www.bilibili.com/video/BV1rY4y1P7er/?p=2&share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1rY4y1P7er'/>
2. 非常**优雅的入门课**,同前面 3Blue1Brown 的微积分本质一样的使用方法。
3. 注意,这个是**入门课**,不算系统课程!
4. **建议看完!**
### 线性代数
#### 整体框架介绍
下面又是我一点点个人理解,好吧,其实就一句话,别担心!线性代数是一个很特别的学科,刚开始很难,中间很混乱,最后很通透,因为全篇都在以不同的角度阐述相同又不同的内容,所以某种意义上,线性代数可以从任何一章节开始学习(当然,实际上要根据教材来,不然很怪啦)
而关于线性代数整体研究什么,我极力推荐下面辅助部分的丘维声先生高等代数第一节高等代数研究对象(就第一节哦!因为这是数学系课程,偏理论,非数同学看多了不合适)
#### 系统性的网课推荐
与高等数学模块相同,这里没有放速成课和考研课,因为笔者认为这两类课程的功利性过强,并且对知识的总结过多,不利于未来深入学习其他内容,因此不算传统学习路线,将速成课放在了最后应试技巧部分(考研课没推荐,因为笔者是数学系同学,这些不清楚,是一点也没看过)
这里只推荐两个网课,如果觉得自身不合适,可以自行去寻找其他更合适的。
##### MIT 版的线性代数
1. 链接:[【麻省理工学院 - MIT - 线性代数(我愿称之为线性代数教程天花板)】](https://www.bilibili.com/video/BV16Z4y1U7oU/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV16Z4y1U7oU'/>
2. 评价:神中神!未来做工程应用的学生很推荐看这个!
##### 宋浩线性代数
1. 链接:[【《线性代数》高清教学视频“惊叹号”系列 宋浩老师】](https://www.bilibili.com/video/BV1aW411Q7x1/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1aW411Q7x1'/>
2. 评价MIT 系列过于强大,宋浩版本显得有些暗淡无光,但实际上宋浩老师版本完全是可以应对考试,如果接受不了 MIT 的版本,还是可以考虑有趣的宋浩老师。
#### 教材推荐
与前面高等数学部分相同,这里只做几个点说明
1. 有一些线性代数的图解书籍或者讲几何意义的,可以看,但这里没做推荐,因为很多书不太严谨,可以自行搜索。
2. 书单链接:[有没有讲线性代数比较好的教材? - 如何表达的回答 - 知乎](https://www.zhihu.com/question/586392502/answer/2913648674)
3. 主推荐还是 MIT 网课老爷子的配套书籍,
4. 尽可能看英文原版,不要害怕。
5. 《线性代数及其应用》千万别看翻译版,有很大问题,要看只看原版!![img](https://cdn.xyxsw.site/v2-704a5d77d767493bada1feccadcd6c4c_720w.webp)
#### 辅助部分
跟上面的高数部分一样,不过对于线性代数来说,可视化的理解会更有效果
##### 3Blue1Brown 的线性代数本质
1. 链接:[【官方双语/合集】线性代数的本质 - 系列合集】](https://www.bilibili.com/video/BV1ys411472E/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1ys411472E'/>
2. 神中神!多看,反复看!不允许学线性代数的人不看这个视频!
3. 其他不多说,和前面高数一样
##### Brilliant
1. 链接:[https://brilliant.org/](https://brilliant.org/)
2. 和高数部分一样,不多说了
##### 丘维声《高等代数》第一节课--高等代数研究对象
这个课程是数学系同学学习的,也是笔者学习的课程,本来不该给非数学系的同学推荐,但是这里面的第一节讲的太好了,能让你很快的构建起一个**大概的框架**,并且能很好的避免传统无脑填鸭式的上来就给你讲行列式的课程体系(**点名批评线性代数紫皮书**,也就是杭电教材,同济大学版的线代)
1. 链接:[【北大丘维声教授清华高等代数课程 1080P 高清修复版 (全 151 集)】](https://www.bilibili.com/video/BV1jR4y1M78W/?share_source=copy_web&vd_source=1958d03181be22cf265b18eeec1314ff)
<Bilibili bvid='BV1jR4y1M78W'/>
2. 再强调一下嗷,就**只看第一节**,也就是 001 和 002 两个视频。因为后续整个内容偏理论,应用层太少,不适合传统工科,但这第一节,绝对能让你搭建一个大概的**框架**,助力后续学习不晕眩!
##### 线性代数可视化手册
- 一个非常好的笔记,总结的很不错,但刚开始看会看不明白(毕竟是总结),建议学完一遍再看
- 链接:[kenjihiranabe/The-Art-of-Linear-Algebra: Graphic notes on Gilbert Strang's "Linear Algebra for Everyone" (github.com)](https://github.com/kenjihiranabe/The-Art-of-Linear-Algebra)
- 别告诉我不会在 GitHub 上下载文件哈(不会就去学下,利用 AI 工具
## 其他部分
### 新生先修课
【Warning】这里别的不能多说只能简略提几点希望你能懂。
1. 这是自愿内容,不是必须的。
2. 合理利用机制,可以考虑替代期中成绩,为部分同学刷分需要(注!不是所有人都要刷分的!具体看 1.6 节正确解读 GPA
3. 这份网课面向的是全体学子,其不一定适合你,或过于简单,或效率不高,但你应该尝试作为独立个体将其与其他课程进行对比,选择合适你自己的,为自己负责。
4. 相信互联网资源的筛选法则。
### 未央学社数学答疑(应试部分)
是不是有点同学会觉得很奇怪,未央学社不是搞技术的吗,好像 java 后端很厉害,实际上这里打个小广告,未央学社除了技术部,还有讲师团和运营部,而讲师团专门负责给大家数学答疑和整理资料,我们构建了**HDU 数学营**,里面有很多资料,比如**往年卷**,比如我们专属出品**复习提纲**等,还有**非常多的同学互帮互助**,不说了,直接来看吧!
#### 未央学社 HDU 数学营
![image-20230801062631288](https://cdn.xyxsw.site/image-20230801062631288.png)
#### 钉钉答疑
我们还提供答疑服务,详细内容可以看下面的推文哈
[未央学社学业答疑服务来啦 | 助力解决学业问题](https://mp.weixin.qq.com/s/FmwT_V8j4we22KzJiHWmtQ)
#### 应试技巧
##### 往年卷
因为知识点不会变化,每年只是侧重有些区别,并且大部分题型还是一样的,因此往年卷有助于快速提分,做 3 份往年卷,你就会发现,欸,好像每年差不多。
##### 速成视频
个人不推荐猴博士,不适合杭电,看了容易挂科。
为了不挂科,速成方面,微信公众号:蜂考,相对合适一些,但仅用于速成!
关于视频资源:可以支持购买正版,也可以 PDDTB 等地方获取。
##### 高分复习顺序(个人推荐版)
这部分内容仅为个人看法,不代表一定能高分,也不代表不这样做拿不到高分。
最完整的复习顺序:知识点→书本例题→课堂例题(一般有 PPT→作业题→书本课后题→往年卷真题
考试题型来源:作业题和例题,因此当回顾作业题完成后,做往年卷会有特别感受。
随时间可不做的优先级(若时间来不及,先砍)
1. 书本课后题
2. 作业题
3. 知识点(这里值得是细看知识点,不是粗看,粗看都不看,直接跳转第 7 步)
4. 课堂例题
5. 书本例题
6. 往年卷真题
7. 如果平时没努力的话,这时候可以开始准备补考了

View File

@@ -0,0 +1,183 @@
# 杭电“失败”指南
## 前言
> 淋过雨的人,也想为别人打伞
毕业很久了,但是回望我的大学生涯,充满了很多遗憾,吃过很多苦头,收获了很多教训,我偶尔会回想,如果当初我如何如何,现在会不会不那么“失败”一些。于是,在某个晚上,有了这篇指南。
谢谢学弟学妹能够抽出时间看这篇“失败”指南,这篇指南以个人角度讲述了一个 CS 学生在上大学的时候收获到的一些经验和教训,或许没那么适用,但是也许可以让学弟学妹的大学生活不会像我一样“失败”。
这篇文章尽可能少的讲故事,更多是实用主义的教训(杂谈篇除外)(里面有太多偏激的观点,说教色彩也很浓厚,仅供参考)。
如果这篇所谓的狗屁指南让你觉得
> 听过很多道理,依然过不好这一生
没关系,勇敢地去做自己热爱的事情就好。
## 杂谈篇
> 如果你是一个对 CS 充满热爱,怀抱一颗技术宅拯救世界的心,那你可以跳过此篇。(其他章节可以读读 (#^.^#))
> 如果你像我一样,是一个明明从小热爱技术,但是有时候有些功利的矛盾人,又或者是大多数对大学充满迷茫,不知道该怎么办的人,或许可以继续看下去。
### 高考败犬:脱颖而出的心态修炼
我所在的学院每年都有或多或少一些学生觉得自己是高考考差才来这里的刚进来校的我也是这样。这种心态我非常能理解但是问题是进来了以后怎么在这所学校脱颖而出PS前提是你想脱颖而出
1. 保持这份不甘心。太多同学在刚进大学的时候踌躇满志,最后四年以后可能也是泯然众人。当初的一份志气也被消磨在宿舍、游戏和无意义的社交中。为了让自己能够脱颖而出,首先要做的就是提醒自己,保持不甘心,保持自己的志气,不要甘心自己已经有的一切,永远觉得自己可以更强,更厉害。
2. 充满野心,渴望成为这个学校最顶尖的那批人。老实说,杭电是一所双非,在未来会对你(大部分人)在很多地方都有些隐性限制,但是,每一所大学最顶尖的那批人,都能够冲破这些束缚。直白些说,即使它是一所双非,但是它在很多领域都有超越一些 211 和 985 的资源和实力。很幸运CS 领域就是其中之一。不用怀疑,它能够提供你所想要的一切。但是资源是有限的,所以如果你想成为很厉害很厉害的人,那么就一定要尽可能去抓住它能够给你的一切资源。
### 攫取者:永远向厉害的人去学习
那么,杭电究竟能够给大家什么资源呢?浓厚的竞赛氛围?浓厚的 CS 氛围?我个人觉得不全是。杭电之所以成为 CS 强校,是因为上述氛围吸引和聚拢了一堆充满理想,热爱技术的人儿。或许你可能只是一名还在迷茫期的新生,但是没关系,去主动靠近和接触他们,永远向比你厉害的人学习,不断提高自己的技能和认知水平。特别是认知。
之所以强调这一点,是因为技能是可以自己通过时间去磨炼的,但是认知的话,如果你根本不知道有"A",怎么可能去主动学习"A"呢?如果你不知道厉害的人他们平时在干什么,他们在学什么,在打什么比赛,研究什么先进或有趣的东西,你怎么可能去学习这些呢?我觉得进杭电的同学,其实"天赋"和"聪明程度"都差不多关键在于信息差和执行力。PShdu-cs-wiki 就是一种缩小信息差的工具)
那么,怎么才能认识到这么多厉害的人,以及向他们学习呢?说白了,就是混进大佬的圈子。作为新生,一个打开局面的方法是,先选择一个方向去钻研学习,结识这个方向的大佬,成为这个方向的大佬,然后认识其他方向的大佬。
问题就转化成,我该选择哪个方向成为我的起点。
### 迷茫中的选择:科研/竞赛/开源/学业/技术/工作
> 犹豫就会败北,世界不是非此即彼,热爱才抵得过岁月漫长
作为新生,我曾一度非常非常非常迷茫,当时最大的问题是,该选择哪个方向发展,是 CTF还是 ACM还是刷绩点争取保研还是专注我热爱的技术做有影响力的开源
我犯过最大的教训有三个,一个是功利主义地拒绝了自己最热爱的方向,二是总在犹豫和后悔自己的选择,三是总觉得不同方向只能选择一个,无法兼顾。
TBD...
## 科研篇
### 选择障碍:怎么选择研究方向
TBD...
### 从 0 入门 AI实践和理论的权衡
TBD...
### 论文相关:从阅读一篇论文说起
TBD...
### 论文相关:头疼的文献管理
TBD...
### 论文相关:好记性不如烂笔头
TBD...
### 经验谈:炼丹师的能力修炼
TBD...
### 经验谈:合作交流及信息渠道
TBD...
### 实践谈:提出 idea 到投稿的经验教训
TBD...
## 竞赛篇
### 四大竞赛对个人成长的收益分析
TBD...
## 开源和个人影响力
### 为什么要培养个人影响力
TBD...
### 如何做人工智能方向的开源项目
TBD...
## 技术篇
### 后悔药:如何选择技术发展方向
TBD...
## 学业篇
### 如何兼顾学业绩点和专业技能培养
TBD...
### 过时的个人谬论:如何聪明且高效地刷绩点
TBD...
### 2023 年以后读研的必要性如何
TBD...
### 保研经验分享
TBD...
## 找工篇
### 后悔药:如何“面向找大厂工作”读大学
TBD...
### 经验篇:高效准备基础知识和笔试考核
TBD...
### 简历篇:如何做一份或许“优秀”的简历
TBD...
### 经验谈:非技术因素在面试中的影响
之所以选择这个话题,一方面是因为这个东西很容易被大家忽略,另一方面这个也比较普适,无论做开发还是算法都可以参考。
#### 面试前 - 个人介绍
在面试前应该准备好自己的个人介绍,除了老生常态的基本信息外,我觉得需要做到既要突出自己的亮点,但是别太过,同时也要根据不同的面试去修改。
先给大家看一个例子:
您好,我叫 xxx是 xx 大学 xx 学院 xx 级学生。自从进入大学以来,我【省略一些内容】。在 xxx 地方实习期间做了 xxx 工作。在平时xxxxx主要讲自己的开源社区贡献、技术博客撰写、竞赛等
**第一就是要尽量介绍地比较“多面”**,不但要说自己在学校和实习中做了什么,还要说一些个人影响力的东西,比如开源社区贡献这一块。其实就是突出一些自己相对于其他候选人的亮点,相比于其他大部分人来说,你的特别在哪。
**第二就是要建立“投缘”机会**,在面试前,搜集到这场面试的部门和小组是做什么,甚至面试官是谁。【省略一些例子】。我想强调的关键是在自我介绍中,**突出自己和这个部门,这个组的 connection寻找尽可能多的共同点和缘分点**。
#### 面试中 - 项目准备
在面试前,还应该准备好自己的项目梳理笔记。实际上,在面试过程中,如果没有提前梳理好自己的项目的逻辑的话,很难在面试现场讲清楚以及让面试官及时 get 到你想表达的点。
一般而言,对于在校期间做的一些项目或者开源项目自己都能比较好地梳理清楚,但是比较难的是在实习过程中,特别是一份复杂的业务实习中梳理自己的产出。我个人认为**面试官比较关注以下几个方面**:一就是业务背景,也就是咱们的业务是什么,大概的架构,发展到哪种阶段,目前的瓶颈等。二就是本人负责的模块是什么,创新点是什么,以及特别重要的是:”我为什么要做这件事!“,三就是这个模块最后的业务收益是多少,怎么去评判收益。可以参考这种逻辑去梳理。
#### 面试前 - 好记性不如烂笔头
上文主要讲了个人介绍和项目梳理,我建议大家把个人介绍和项目梳理都放在一个 note 里面,每次面试前半个小时到一个小时回顾下自己的 note以及根据面试岗位和小组来修改下。这样的好处在于每次都回顾下自己的项目和介绍面试过程中有参考不会慌。等面试次数多了你就会发现其实**每场面试都是在重复介绍你 note 里面的内容**。
#### 面试中 - 换位思考很重要
**面试过程中的一大禁忌就是不考虑面试官的感受,一股脑介绍自己的项目**。一方面,面试官无法在短时间内吸收到你想表达的内容,另一方面,你一直噼里啪啦输出面试官听不懂的东西,面试官也会特别烦躁。
一个比较好的方式是:每次介绍完一段时,就停下来,反问面试官:您看您对这个项目的 xx 有什么疑问吗?比如说你介绍完项目背景后,就记得停下来,反问下,您看你对这个项目背景有什么疑问吗。
除了每次介绍完一段就停顿时,还有一个需要注意的点在于,不要梳理完项目以后,就完全按照项目梳理的内容去念,要注意观察面试官的反应,如果感觉他其实并不怎么感兴趣,就想办法赶紧结束。
#### 面试中 - 反问阶段
反问阶段是一个及时获取信息的好机会。不同面试阶段有不同的提问。一面基本是你的同事或者你的 mentor这个时候可以专注问一些工作内容工作氛围等比较实际的话题。对于三面来说一般是大老板这个时候你要抓住机会和他交流下一些比较 high-level 的东西,因为以后很少有机会去和这样 senior 的人交流。话题诸如:职业发展路径、发展前景、绩效考核、我会被分配到什么具体组。
如果在每场面试的时候,你想知道自己大概的表现,你可以反问阶段,非常非常非常委婉地提问:您看我这次面试还有什么可以提升的地方吗?
## 结语
TBD...

View File

@@ -4,20 +4,20 @@
大学的真意是综合而全面的培养一个人。为什么大学有这样的职责?因为这是人最后的受教育阶段(研究生、博士生也是在大学里接受教育)。从接受教育开始到走向社会为止,这期间是人,变成一个人最为宝贵的阶段。
<strong>大学是唯一可以与来自五湖四海、不同学科背景的人共处一个校园的时期,这里就应该是开放而需要激烈思想碰撞的地方</strong>。大学是专业的,但同时更是广博的,我们在黄金的年龄来到这里,就不要轻易的错过这样疯狂吸纳不同看法的机会。同样,大学是未来所有可能性的孵化器,请保持一颗尝试新事物的心,索取大学所能给予的任何一切,并让它成为提升自我的工具。
**大学是唯一可以与来自五湖四海、不同学科背景的人共处一个校园的时期,这里就应该是开放而需要激烈思想碰撞的地方**。大学是专业的,但同时更是广博的,我们在黄金的年龄来到这里,就不要轻易的错过这样疯狂吸纳不同看法的机会。同样,大学是未来所有可能性的孵化器,请保持一颗尝试新事物的心,索取大学所能给予的任何一切,并让它成为提升自我的工具。
工具,我并不避讳这个词。只不过我并不想将这个词与人画等号。人非工具,而是使用工具的。我们的祖先经过数百万年的努力和尝试,才学会使用并创造工具,目的就是不再沦为工具,我们站在 21 世纪也不应该心甘情愿的将自己锻造成一个工具,这是返祖与退化的表现。
21 世纪是人类对高科技和超级想象力、创造力最渴求的百年。一个想法和主意胜过千万个重复的机械化劳动,虽然后者也能带来一定程度的好处,但这并不我们的目标。大学是否能迸发出惊人的创造力,在于学生和教师的思想与行为。而不同的学科交叉和碰撞会让创造力和科技的创新更大概率出现。
听说乔布斯有对禅宗修习的经历,而他的工作可能并不与禅宗搭边。但他的成功却不能不说与他广泛的涉猎有关。工具是没有办法创造工具的,只有人才能创造。<strong>我们大学生应该去思考在大学四年如何想办法把自己锻造成真正的人。</strong>
听说乔布斯有对禅宗修习的经历,而他的工作可能并不与禅宗搭边。但他的成功却不能不说与他广泛的涉猎有关。工具是没有办法创造工具的,只有人才能创造。**我们大学生应该去思考在大学四年如何想办法把自己锻造成真正的人。**
这个人不是做题的机器,不是刷题的工具,不是眼中只有考高分的单一生物,当然更不可能是成天浑浑噩噩、行尸走肉的颓丧者、躺平者。说到这里,可能会讲,难道不躺平去卷吗?并不是,我反对 “卷”,<strong>因为 “卷” 的含义是无意义的恶性竞争和没有实际突破的简单重复劳动,边际效益递减的不划算却无奈的选择。</strong>“卷” 不等于 “勤奋” 、 “创造” 和 “想要变得更强” ,将之画等号我认为是当前观念中一个很大的误区。<strong>我们需要大学生有自己的思考和创造力,需要大学生是一个综合全面发展的人。</strong>只有这样大学才有活力、希望,社会才有动力,国家才有未来。
这个人不是做题的机器,不是刷题的工具,不是眼中只有考高分的单一生物,当然更不可能是成天浑浑噩噩、行尸走肉的颓丧者、躺平者。说到这里,可能会讲,难道不躺平去卷吗?并不是,我反对 “卷”,**因为 “卷” 的含义是无意义的恶性竞争和没有实际突破的简单重复劳动,边际效益递减的不划算却无奈的选择。**“卷” 不等于 “勤奋” 、 “创造” 和 “想要变得更强” ,将之画等号我认为是当前观念中一个很大的误区。**我们需要大学生有自己的思考和创造力,需要大学生是一个综合全面发展的人。**只有这样大学才有活力、希望,社会才有动力,国家才有未来。
我知道大学可能并不如你们想象的那般美好,有不负责的、划水上课的老师以及你看不惯的、瞧不起的种种行为,但这并不是自己选择放弃和抱怨的理由。因为,我相信大学还有认真负责的老师、有思想的学者以及有想法的同学,我们需要和自己钦佩、三观相符的人多接触,让自己成为你佩服的人的样子,而非因为种种不好的现象而选择全盘的否定、甚至自暴自弃。
<strong> 要有自己的目标,年轻是实现自己目标最好的资本。</strong>为了这个目标,在大学里徜徉、像海绵一样吸纳如水般的知识和见识。博采众长而非简单功利。可能你今天听了不重要的课(相对于专业课),但只要是值得听的老师讲的有涵养的课,你就不算枉费时光。因为这样的经历并不会让你浪费时间,而会在未来的某刻显示出它的价值。
** 要有自己的目标,年轻是实现自己目标最好的资本。**为了这个目标,在大学里徜徉、像海绵一样吸纳如水般的知识和见识。博采众长而非简单功利。可能你今天听了不重要的课(相对于专业课),但只要是值得听的老师讲的有涵养的课,你就不算枉费时光。因为这样的经历并不会让你浪费时间,而会在未来的某刻显示出它的价值。
不要让自己的大脑空空,刷抖音、看游戏直播或者看无聊的视频或许是娱乐的方式,但这些是你可以在余生每天都可做的最没有技术含量的事,而且这些并不会让你大脑填入真正有价值的东西。<strong>去做只有大学时光才能做的事吧!</strong>丰富自己、创造自己、提升自己。多看一页经典的著作,这是人类上百年乃至上千年思想的精华。多认真的听一节有价值的课吧,这是老师积几十年的学识认真准备的盛宴。
不要让自己的大脑空空,刷抖音、看游戏直播或者看无聊的视频或许是娱乐的方式,但这些是你可以在余生每天都可做的最没有技术含量的事,而且这些并不会让你大脑填入真正有价值的东西。**去做只有大学时光才能做的事吧!**丰富自己、创造自己、提升自己。多看一页经典的著作,这是人类上百年乃至上千年思想的精华。多认真的听一节有价值的课吧,这是老师积几十年的学识认真准备的盛宴。
可能你会说,大学没有好的课程,老师都在划水。如果你有这样的看法,我想说,可能是你了解的太少所致,多去了解一下一定有让你满意的老师。另外,为什么大学会出现这样不好的课程呢?因为老师不愿意好好上课。为什么老师不愿意好好教学呢?因为在功利化的指挥棒下,好好上课是性价比最低的行为。如此,你就知道大学只知道功利化、工具化的接受教育,而不培养人文素养的恶果了吧!

View File

@@ -1,8 +1,6 @@
# 竞赛指北
> 本部分带有强烈主观色彩,仅为笔者作为技术人员参(陪)与(跑)过一年半的竞赛(如新苗、大创、互联网+、服务外包、电商、大小挑等含文本元素的竞赛)的感想。仅供参考。如有其他看法,欢迎留言。
# 竞赛可以带来什么
## 竞赛可以带来什么
“哪个比赛更有含金量” 的问题应该是很多同学会关心的,然而比赛对人的帮助是因人而异的。比起列一个所谓的比赛含金量排名,笔者认为认清自己想要的是什么,再去评判比赛含金量才是有意义的。
@@ -16,17 +14,20 @@
- 如果你想锻炼自己的技术
像 ACM 等纯技术类比赛,利用比赛锻炼技术是完全可行的;如果是含文本元素的竞赛,利用比赛驱动自己学技术相对有利有弊。利在有人催你做项目,你可以直接按照文本给的要求写项目而不用自己想 Idea 。一旦获奖,对做技术的人而言也是正反馈。而且如果团队走的足够远,会有人帮你推广你做的项目。弊端也很明显。很多含文本元素的比赛并不注重具体落地,只要文本写的够好就能入围。这种情况下
像 ACM、CTF 等纯技术类比赛,利用比赛锻炼技术是完全可行的;如果是含文本元素的竞赛,利用比赛驱动自己学技术相对有利有弊。利在有人催你做项目,你可以直接按照文本给的要求写项目而不用自己想 Idea 。一旦获奖,对做技术的人而言也是正反馈。而且如果团队走的足够远,会有人帮你推广你做的项目。弊端也很明显。很多含文本元素的比赛并不注重具体落地,只要文本写的够好就能入围。这种情况下
1. 有可能组内成员提出一些工作量相当大的需求(例如一个人全栈)或者以现阶段能力完全做不了的需求,来圆上之前画的饼。
2. 当发现 “只要糊弄一下套个空壳也可以” ,你可能就不想把项目落地了。这会极大地挫伤一个人独立开发完整项目的积极性。
尽管如此,对于多数杭电学生而言,参加竞赛是最好的锻炼技术的方式,对杭电而言,竞赛是不可或缺的一部分。
- 如果你想拓展人脉圈
笔者的很多朋友也都是通过竞赛认识的。通过竞赛认识朋友是很不错的选择,团队项目不仅可以增加彼此之间的交流机会,也可以让你根据这位队友在协作中的表现估摸对方的品行(当你和队友为了赶比赛 DDL 一起 Debug 到两三点、或者你发现队友摆烂什么代码也不写,你大概会更深地理解到为什么这样说)。另外,如果竞赛打的够多,也会有组员主动邀请你参加其他的项目,认识更多的人。
除了志同道合的朋友,其实你也会更容易接触到老师。对于一般路过摆烂大学生来说,见到老师无非就是在讲台上,很少有面对面交流的机会。而在比赛里,你可以和你的指导老师有更深的接触。当然,这些指导老师有很为学生着想的,也有视学生为廉价劳动力的,要注意辨别。
# 项目来源(含文本元素的竞赛)
## 项目来源(含文本元素的竞赛)
- 祖传项目
@@ -42,7 +43,7 @@
好处是本身就是落地项目,在论证项目可行性时具有很强的说服力,这类项目也相对来说会容易获奖。对于想要做实际落地项目的技术人员来说是不错的锻炼机会。
坏处是甲方<strong>可能</strong>提出大量需求,技术人员需付出大量精力跟进,然而因为项目本身参与比赛而无法收取原定的外包费用,技术人员成为白菜大学生被白嫖(当然这个潜在可能性带来的坏处也因人而异,如果不在乎频繁改动需求 / 愿意做没有外包费用的无偿奉献,只想锻炼自己,那就无所谓)。
坏处是甲方**可能**提出大量需求,技术人员需付出大量精力跟进,然而因为项目本身参与比赛而无法收取原定的外包费用,技术人员成为白菜大学生被白嫖(当然这个潜在可能性带来的坏处也因人而异,如果不在乎频繁改动需求 / 愿意做没有外包费用的无偿奉献,只想锻炼自己,那就无所谓)。
- 自立初创项目
@@ -52,7 +53,37 @@
不过所有项目都始于初创项目,还是鼓励大家如果有自己的想法可以考虑初创项目。以个人体感而言,参与一个祖传项目虽然获奖相对容易,但作为一个项目的初创人,从组织团队、开发项目、打各大比赛到拿奖加 GPA ,这样的经历哪怕没拿奖也是很不错的锻炼。
# 数据科学竞赛
## CTF (信息安全竞赛)
> CTF 能满足你对黑客的一切幻想
计算机信息安全竞赛在社会上的知名度并不高,但它和 ACM 一样是强技术竞赛,无任何 PPT 环节以及展示环节(除了一些少数比赛如国赛省赛有知识竞赛这一环节/赛道技术就是唯一取胜的关键。CTF 是计算机安全竞赛的一种赛制全称“Capture The Flag”即夺旗赛比赛选手需利用自己的计算机安全技术完成挑战成功拿下题目后会获得一个使用`flag{}`包裹的字符串这个字符串就是flag提交到平台上就可以获得一定的分数。
杭电的 CTF 竞赛历史悠久Vidar-Team 信息安全协会的主打比赛就是 CTF据本文档编写之时算起已有 15 年的历史,大大小小国内国外获奖无数,本 wiki 的计算机安全部分也由信息安全协会编写。
![](https://cdn.xyxsw.site/prize.png)
### 优点
信息安全竞赛是强技术类竞赛,如果你选择计算机安全作为自己的主攻方向,该竞赛将包含几乎所有计算机安全的内容,在一个竞赛里就可以从入门到入土。
CTF 在计算机安全类招聘,以及计算机安全类研究生招生中占有很大作用,安全类企业在招聘时更喜欢 CTF 选手,就好像算法岗更喜欢 ACM 选手一样(虽然现在两者的就业都没有以前好了)。
计算机安全也是一个挑战性很强的领域,在国外有很高的研究热情,如今在国内也受政府大力支持,比如强网杯由河南省政府主办,奖金高达 500 万元,西湖论剑由浙江省政府主办,奖金也很丰厚。除此之外,在计算机安全领域还有漏洞赏金这一说,大型企业都会有 SRCSecurity Response Center安全应急响应中心这种平台上交该企业的漏洞就可以获得赏金比如微软 RDP 远程代码执行漏洞(通过一定手段使得另一台电脑执行任意代码)赏金高达 10 万刀。VMware 虚拟机逃逸在虚拟机内通过一定的手段可以在主机上执行任意代码20 万刀等越有挑战性的领域赏金越高。国内的SRC平台https://www.anquanke.com/src
![](https://cdn.xyxsw.site/src.png)
### 缺点
CTF 的缺点在于受学校支撑不大学校不重视该比赛但又有什么关系呢CTF 浙江省省赛由杭电“主办”为省A类竞赛获一等奖可加 0.7 GPA大约能让你三等奖学金450元变一等奖学金1500元但奖学金对于找工作其实没啥用并且每队3人奖金 3 千元。全国大学生信息安全竞赛为B类竞赛和省赛同等待遇。除该两个比赛以外剩下的比赛学校均不认可近年来强网杯等政府主办比赛也稍微提高了认可度。但浙江省省赛在社会上的认可度远不如国赛和其他企业/战队主办的比赛。如果你想依靠竞赛去争取杭电可怜的保研名额,老老实实打数模这种杭州电子数模大学高度认可的比赛,不要选 CTF。
CTF还有的缺点也是目前热门领域的通病发展速度过快后来者需要学的东西越来越多越来越难越来越边缘。计算机安全作为一个对抗性比较强的课题像人工智能里面的对抗性学习一样两个AI互相下棋发展速度是日新月异的所以入行越晚风险越大。
---
更多可以参考计算安全章节
[传送门](/6.%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%AE%89%E5%85%A8/6.%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%AE%89%E5%85%A8)
## 数据科学竞赛
这个比赛在一些学校相较而言比较冷门但是含金量不低奖项也相较而言比较丰厚如果对数据科学比较感兴趣4.8章节)的同学可以进一步了解
@@ -65,7 +96,7 @@
竞赛公众号Coggle数据科学
知乎专栏:机器学习理论与数据竞赛实战
# 数模竞赛(某学长的建议)
## 数模竞赛(某学长的建议)
高中阶段,可能大家很多都把很多的精力放在了主修的课程中,常参加竞赛的精力少之又少,而大学和高中很大的一个不同点就在于,我们可以不把所有的精力都放在课程的学习上,还有很多的选择,比如选择一个自己感兴趣的社团,或者选择一个适合自己的竞赛,
@@ -86,12 +117,10 @@
最后,祝各位想参赛的学生最后可以拿到自己理想的奖项哦。
# 智能车竞赛简介
## 智能车竞赛简介
杭电智能车比赛主要分为三大部分:竞速(电磁),竞速(视觉)与创意组.
由于笔者是创意组的,对其他组别不是很了解,就来介绍一下我们组别的情况。我们组别全称是智能车百度创意组,是由百度与鲸鱼机器人赞助的一个比较新的组别(目前是第三年,不过也开始卷起来了),该组别与传统组别的一个比较大的不同是对于硬件方面的要求并不高(但也是需要了解的,像 arduino stm32 这些稍微都得玩的起来),侧重会偏向软件算法方向。百度创意组总体分为两个阶段,线上赛和线下赛,线上赛的任务有点像是 kaggle 打榜,不过是百度官方命题,并且在飞浆平台上进行测试的,本质考验的就是你对神经网络的理解和调参(炼丹),如下图所示
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnQe2AYHX93NUz6Sfoq3hUPd.png)
![](https://cdn.xyxsw.site/boxcnQe2AYHX93NUz6Sfoq3hUPd.png)

View File

@@ -1,6 +1,6 @@
# 小心项目陷阱
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnPmQ725zYTxiyo2LqQkphib.png)
![](https://cdn.xyxsw.site/boxcnPmQ725zYTxiyo2LqQkphib.png)
## 辨别项目质量
@@ -52,7 +52,7 @@
但是大家参与之前你一定要想你的能力是否等于这个项目的量级,一般情况下,要么你技术特别强,要么可能会存在一定的问题。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnPSolGcUy1R0Dk2FUhPaLLc.png)
![](https://cdn.xyxsw.site/boxcnPSolGcUy1R0Dk2FUhPaLLc.png)
所以说,还是那句话,小心甄别。

View File

@@ -11,6 +11,8 @@
::: warning 🤣
[与人合作中的 “生死疲劳” 哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1494y1o7jp)
<Bilibili bvid='BV1494y1o7jp'/>
**一定要看看这个**
:::

View File

@@ -10,11 +10,11 @@ GPA一个酷似成绩的东西
毕竟在高中,一份理想的成绩意味着一个光明的未来。
但是我想说,<strong>在大学,请摆脱高中的绩点惯性</strong>
但是我想说,**在大学,请摆脱高中的绩点惯性**
在大学,绩点其实只是一个获得资源的工具,高的绩点并不代表光明的未来,也不能够代表高超的学习能力和扎实的专业知识。同时我们要明白,与高中截然不同的是,大学是一个多目标优化问题,绩点只是优化问题的一个维度,而非所有。
> <strong>author晓宇</strong>
> **author晓宇**
所以本文会讲述 GPA 能够带来什么,什么是一个合理的对待 GPA 的态度,如果需要,如何获得一个较高的 GPA 。
@@ -90,7 +90,7 @@ B. 大一进来从来不太在意 GPA大部分经历在研究 Github 项目
当你已经成为大学生的时候GPA成绩不是和一个人的优秀的呈正相关的这不过是一个通往一些资源的途径同样的也有很多资源可以不用 GPA可以靠个人硬实力去争取例如实习例如科研助理云云。只是说如果你不知道干啥先认真学好专业课知识是一个保有收益的事情但当有其他选择的时候可以权衡但也不可走另外一个极端则完全不在乎 GPA在职业规划并不清晰的时候不要自废道路。
最后想说的是,一个获得资源的玩具罢了,不值得让你<strong>常沉苦海,永失真道</strong>
最后想说的是,一个获得资源的玩具罢了,不值得让你**常沉苦海,永失真道**
## GPA 补充内容:

View File

@@ -6,13 +6,13 @@
## 序言:一组数据看出国
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcndFjrKQMhZJsH1vN1fEfaQb.png)
![](https://cdn.xyxsw.site/boxcndFjrKQMhZJsH1vN1fEfaQb.png)
点开图片可以看到左边是西交利物浦的出国数据,中间是杭电的数据,右边是成都电子科技大学的数据,可以看出西交利物浦每年去名校的数量大概是杭电一年的 20-40 倍,成电是杭电的一年的 10 倍左右,杭电出国数据实际上只有寥寥几个名校,剩下的则是一些英国院校。
这其中原因除了杭电高性价比的就业环境,双非院校选择出国深造的人数较低,我认为比较还有一点则是信息差。优秀的大学都有他们自己的飞跃手册,其中会介绍每个国家的优劣,以及申请的一些注意事项,详见下图。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnKMzGr9LSrXWmKxa1lSM1zJ.png)
![](https://cdn.xyxsw.site/boxcnKMzGr9LSrXWmKxa1lSM1zJ.png)
优越的校友资源和前人留下的数据和方案,加下信息差的叠加,就像符合幂律分布的无标度网络一样,只会让我们的差距越来越大,在感叹其他学校飞跃手册的优越性的同时也发现了一些不可参考性,因为在其中也存在着很多问题,在这些学校中,可能名校读博就是老师写个推荐信就有了面试的机会,可能去港大 / G5 就是大学四年均分 80 分的难度。有很多资料在不同的角度,我们很难参考,所以我不经会想问?那我们呢,我们考多少多少分能够去什么学校,我们想要直博应该怎么准备,所以我打算完成这份出国留学的手册,能够为学弟学妹们铺路,同样希望后面也能够有学弟学妹做完善和补充。

View File

@@ -4,11 +4,11 @@
相信转专业的人里,不少是慕 HDU 的强势理工科热门专业来的。但是在转专业之前,你需要先确认以下几点。
1. 你是<strong>跟风</strong>听你家七大姑八大姨说这个专业好,才想转来这个专业的吗?
2. 你确定你<strong>所向往的</strong>和这个专业所学的<strong>相关</strong>吗?有没有比这个专业更贴切的选择?
3. 你确定你能良好适应(<strong>至少不反感</strong>)这个专业所学的专业课吗?
1. 你是**跟风**听你家七大姑八大姨说这个专业好,才想转来这个专业的吗?
2. 你确定你**所向往的**和这个专业所学的**相关**吗?有没有比这个专业更贴切的选择?
3. 你确定你能良好适应(**至少不反感**)这个专业所学的专业课吗?
以上的问题,如果有觉得不确定的,也没关系,你至少有一学期在学校里探索。可以是问该学院的学长学姐的感受,可以是进研究相关专业知识的社团学习,也可以是自己研究。总之,不能转专业转得迷迷糊糊,因为虽然 HDU 转专业机制比较友好,<strong>但转专业机会只有一次</strong>,如果你转进去之后发现自己完全不适应,那也只能自认倒霉。
以上的问题,如果有觉得不确定的,也没关系,你至少有一学期在学校里探索。可以是问该学院的学长学姐的感受,可以是进研究相关专业知识的社团学习,也可以是自己研究。总之,不能转专业转得迷迷糊糊,因为虽然 HDU 转专业机制比较友好,**但转专业机会只有一次**,如果你转进去之后发现自己完全不适应,那也只能自认倒霉。
像笔者本人最初其实想做游戏开发,本身也热爱绘画之类的艺术。当年只觉得游戏开发和计算机有关,一门心思转计算机,后来转成功之后才发现其实数媒的培养计划更贴合笔者想学的,而现在所在的计科学得更多的是计算机理论方面的知识,也跟游戏开发不搭边。
@@ -29,16 +29,16 @@
:::
转专业填报截止时间一般是在期末考试结束前后,届时<strong>最多填两个</strong>意向专业。
转专业填报截止时间一般是在期末考试结束前后,届时**最多填两个**意向专业。
转专业公示时间一般在开学前后。在转专业结果公示一周内,<strong>可以申请放弃转专业</strong>,此时视作已用过一次转专业机会,<strong>不可再次转专业</strong>。所以如果是非某个专业不去,建议只填报一个意向专业,以防被第二个专业录取,失去转专业资格。
转专业公示时间一般在开学前后。在转专业结果公示一周内,**可以申请放弃转专业**,此时视作已用过一次转专业机会,**不可再次转专业**。所以如果是非某个专业不去,建议只填报一个意向专业,以防被第二个专业录取,失去转专业资格。
## 转专业后的选课
在转专业公示结束后,转专业才正式生效。在公示期期间,如果想提前选课,需要走特殊退改选;也可以等转专业生效后再正常选课。
需要注意的是,<strong>你必须退掉原专业所有的课程</strong>。如果在选课结束后,你仍有未退的原专业课程,你必须含泪又交学费又上课,说不好还要考这个课的试。其中要特别注意原专业的短学期实践课,这个课程比较容易被忽视。
需要注意的是,**你必须退掉原专业所有的课程**。如果在选课结束后,你仍有未退的原专业课程,你必须含泪又交学费又上课,说不好还要考这个课的试。其中要特别注意原专业的短学期实践课,这个课程比较容易被忽视。
在排课时,请找到你转入专业的培养计划,根据培养计划的<strong>课程号</strong>进行选课而不是课程名。HDU 有些课程同名不同号,如果选择了同名不同号的课程,只能寻求课程替代(而且有概率不成功)。这种情况常见于你发现你原来专业的课程和转入专业的某课程名字一样,你懒得换了,殊不知这两个课程完全不是一个课程号,喜变纯纯冤种。
在排课时,请找到你转入专业的培养计划,根据培养计划的**课程号**进行选课而不是课程名。HDU 有些课程同名不同号,如果选择了同名不同号的课程,只能寻求课程替代(而且有概率不成功)。这种情况常见于你发现你原来专业的课程和转入专业的某课程名字一样,你懒得换了,殊不知这两个课程完全不是一个课程号,喜变纯纯冤种。
另外,建议根据开课班级排课。有些课程虽然课程号相同,但可能开给不同学院。比如计算机学院的课程经常和卓越或计算机二专业的一些课程同号,如果你选了其他专业的开课班级的班,期末考试可能会不一样(如计科和卓越的电路与电子学课程号同号,但在 20 级是分开期末考试的)。建议看清开课班级再选课。

View File

@@ -10,15 +10,15 @@
概括一下:摒弃伸手,被动思维,能够主动争取各种机会,带着一个能够独当一面的能力进入实验室,与老师能够形成合作关系。
<strong>能力上:</strong>目前计算机上的科研主要在两大方向,第一大方向是 AI关于这件事情是不是畸形要后期在讨论第二大方向是系统数据库
**能力上:**目前计算机上的科研主要在两大方向,第一大方向是 AI关于这件事情是不是畸形要后期在讨论第二大方向是系统数据库
对于数据库与系统,我目前还没有涉及
<strong>领域的基础能力:</strong>这里要我力推我们的课题教程,有较好的 AI 路线图,尽管 AI 有非常多子方向,如 NLP,CV多模态CV 下面又有检测 语义分割NLP 又有推荐系统等云云,但是无论如何他们的源头都是 MLPMLP 的源头都是多维线性回归,都是基于统计学习理论体系下,都是使用 Pytorch,都要学习数学理论体系,所以是可以要有一套类似的培养体系的。视觉被推荐 cs231n NLP 被推荐 CS224n。
**领域的基础能力:**这里要我力推我们的课题教程,有较好的 AI 路线图,尽管 AI 有非常多子方向,如 NLP,CV多模态CV 下面又有检测 语义分割NLP 又有推荐系统等云云,但是无论如何他们的源头都是 MLPMLP 的源头都是多维线性回归,都是基于统计学习理论体系下,都是使用 Pytorch,都要学习数学理论体系,所以是可以要有一套类似的培养体系的。视觉被推荐 cs231n NLP 被推荐 CS224n。
论文的阅读能力:在了解一个领域的时候,最开始会发现什么词都不懂,一篇文章无论是从语言上还是英文上都无法阅读,所以能否具备快速阅读并读懂一篇文章的能力也是非常重要的。
<strong>如何寻找老师上:</strong>
**如何寻找老师上:**
学校内和学校外都可以寻求合作,在学校内,

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -1,6 +1,14 @@
# 2.1.1 悲壮的学习方式
# 现状
## 现状
::: tip
引自上海交大生存指南
[https://survivesjtu.gitbook.io/survivesjtumanual/li-zhi-pian/bei-zhuang-de-xue-xi-fang-shi](https://survivesjtu.gitbook.io/survivesjtumanual/li-zhi-pian/bei-zhuang-de-xue-xi-fang-shi)
:::
古人刻苦学习的故事,直到现在还在我们的身边不断上演。学生趴在山一样高的习题集边上苦苦奋斗,绝对是我校作为国内一流大学的亮丽的风景线。
@@ -8,7 +16,7 @@
我无意全盘否定同学们吃苦耐劳的精神,但这份精神充其量只能称为悲壮。我们耗费了大量的时间和精力掌握的那些考点、技巧,在真正的知识殿堂里根本登不上大雅之堂。哪怕我们特征值求得再熟练,积分积得再复杂,中国的载人飞船也不会因此而顺利上天。
# 解决
## 解决
学习的时候,不要有负担心理。很多同学在学习知识的时候带着一种学不完或者学不会我就上吊算了的心态,其实这是比较危险的一种精神状态。

View File

@@ -1,16 +1,22 @@
# 2.1.2 浮躁的心理状态
# 现状
## 现状
> 我明明很努力了,但是就是学不懂,群里的同学好像啥都会 WOC<br/>我周围的同学怎么参加竞赛的科研经历丰富的都有就我是废物呜呜呜<br/>我的同学啥都有了但是我什么都没<br/>为什么我室友都脱单了我还是单身狗
> 我明明很努力了,但是就是学不懂,群里的同学好像啥都会 WOC
>
> 我周围的同学怎么参加竞赛的科研经历丰富的都有就我是废物呜呜呜
>
> 我的同学啥都有了但是我什么都没
>
> 为什么我室友都脱单了我还是单身狗
浮躁,往往来源于和他人的比较是具有社会属性的我们的人之常情。
然而,我们往往不能从中获得任何鼓励反而深受打击。
# 解决方案
## 解决方案
如果我在这里说戒骄戒躁一定会被打的(逃)
如果我在这里说戒骄戒躁一定会被打的逃)
学不懂一门课程,大可不必着急,慢慢来,也可以问问学长学姐或者思考一下这门课到底为什么如此组织。
@@ -26,4 +32,4 @@
如果实在不行,来找 ZZM 聊聊吧。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnPDWiNgkgppK1XWq5cRQ71b.jpg)
![](https://cdn.xyxsw.site/boxcnPDWiNgkgppK1XWq5cRQ71b.jpg)

View File

@@ -6,9 +6,11 @@
然后你要慢慢询问他的问题,接着你要问各种问题各种检查然后去看,如果有十个人一百个人都这么问,你肯定会受不了的吧。
事实上, 如果希望能提高得到回答的概率, 提问者应该学会如何更好地提问. 换句话说, 提问者应该去积极思考 "我可以主动做些什么来让对方更方便地帮助我诊断问题".
事实上如果希望能提高得到回答的概率提问者应该学会如何更好地提问换句话说提问者应该去积极思考 "我可以主动做些什么来让对方更方便地帮助我诊断问题".
如果你的提问方式非常不专业, 很可能没有人愿意关注你的问题, 因为这不仅让人觉得你随便提的问题没那么重要, 而且大家也不愿意花费大量的时间向你来回地咨询.
如果你的提问方式非常不专业很可能没有人愿意关注你的问题因为这不仅让人觉得你随便提的问题没那么重要而且大家也不愿意花费大量的时间向你来回地咨询
<Bilibili bvid='BV1om4y1H71S'/>
## 解决
@@ -28,14 +30,39 @@
问题还是没有解决,现在我该怎么做?
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnhuhE7qBLHyJKaesHGC033b.png)
![](https://cdn.xyxsw.site/boxcnhuhE7qBLHyJKaesHGC033b.png)
欢迎大家阅读
### 关于截图
[Stop-Ask-Questions-The-Stupid-Ways/README.md at master · tangx/Stop-Ask-Questions-The-Stupid-Ways](https://github.com/tangx/Stop-Ask-Questions-The-Stupid-Ways/blob/master/README.md) 别像弱智一样提问
如果你在问问题的时候掏出一张手机拍电脑🤳🖥️的图片,那么大概率会让想要帮助你解决问题的学长血压升高然后放弃回答你的问题。
[https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md) 提问的智慧
除非遇到一些特殊情况(例如你的电脑进 BIOS 了),只能手机拍照,也请保证图片清晰便于识别。
![](static/02.jpg)
在 wiki 的[2.2 优雅的使用工具](2.2优雅的使用工具.md),有推荐一些好用开源的截图工具
不过一般情况来说Windows 的组合键`Win+Shift+S`截屏,在任意窗口按下这个组合键便可进入截屏模式,按住鼠标左键拖动框选区域即可截屏,使用`Ctrl+V`操作将截屏内容粘贴到想要保存的地方;如果已经登录了 QQ那么 QQ 的截图快捷键默认是`Ctrl+Alt+A`,同样使用`Ctrl+V`粘贴截屏内容。
ps:QQ 有长截图的功能,妈妈再也不用担心我不会滚动捕捉了!
记住这两个快捷键已经足够满足你对截图的 90% 的需求了
### 橡皮鸭
> 来自伯克利大学的学习建议
当遇到问题时,除了截图外,试着组织语言来解释你遇到困难的地方。
![](static/01.jpg)
**这并不需要一个找到懂得如何解决问题的人 (或者甚至是一个人 —— 这种做法通常被称为橡皮鸭,因为你可以把一只橡皮鸭当作你的练习对象) ,因为主要目标是让你弄清楚你自己的想法,弄清楚你的理解和代码到底在哪里卡住了。这样你可以知道应该专注于哪一部分,以便更好地理解。**
### 欢迎大家阅读
[Stop-Ask-Questions-The-Stupid-Ways](https://github.com/tangx/Stop-Ask-Questions-The-Stupid-Ways/blob/master/README.md) 别像弱智一样提问
[How-To-Ask-Questions-The-Smart-Way](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md) 提问的智慧
## 关于如何搜索代码
@@ -57,11 +84,11 @@ cv.waitKey(0)
接下来,我会去搜索每行代码的作用:(以下是搜索后我做的注释)
```python
import cv2 as cv # 调opencv库
import cv2 as cv # 调 opencv
img = cv.imread('lbxx.jpg',1) # 读取图片(“图片路径”)
img_1 = cv.cvtColor(img,cv.COLOR_BGR2GRAY) # 转换成灰度图(图片, 颜色模式)
cv.imshow('gray',img_1) # 展示图片展示img_1为灰度图
cv.imshow('colour',img) # 展示图片展示img为彩色图
img_1 = cv.cvtColor(img,cv.COLOR_BGR2GRAY) # 转换成灰度图(图片,颜色模式)
cv.imshow('gray',img_1) # 展示图片(展示 img_1 为灰度图)
cv.imshow('colour',img) # 展示图片(展示 img 为彩色图)
cv.waitKey(0) # 保存展示窗口打开
```

View File

@@ -1,12 +1,12 @@
# 2.1.4 书籍的盲目崇拜
# 现状
## 现状
很多同学在学习一个知识的时候,总是喜欢
"我们要学 C 语言,我买一本大黑书看看!"
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnqsCWmUTDr5UDLYca9YkhHh.png)
![](https://cdn.xyxsw.site/boxcnqsCWmUTDr5UDLYca9YkhHh.png)
诚然,上面的各种书写的非常好,但是我们需要思考的是,阅读这些真的能达到我们想要的目标吗???
@@ -14,7 +14,7 @@
通常情况是,如果你阅读了一句话,用了解释这个词的意思用了三个你不懂的额外的词汇去解释,你去查这三个词汇的时候,又发现了五个你不懂的,无限循环下去。
# 解决
## 解决
因此,当你只是为了学习一个简单的知识,或者说为了完成一个简单的目标的时候,肝书可能不是最高效的选择。最高效的方法可能是需要什么的时候就去学习这么一个单一的知识点,并且将他和现有的体系联系起来

View File

@@ -18,4 +18,4 @@
在你完成这份讲义的时候,希望你可以有选择的阅览一部分,然后带着问题去看某些课,效率也会高很多。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnSq1JzWhVrFs3MePPzp5Txg.jpg)
![](https://cdn.xyxsw.site/boxcnSq1JzWhVrFs3MePPzp5Txg.jpg)

View File

@@ -1,6 +1,6 @@
# 2.1 高效的前提:摆脱高中思维
# 高中思维
## 高中思维
高考,诚然为大众提供了阶级跃迁的途径
@@ -12,20 +12,34 @@
就算你把课本上的内容搞得再烂熟,绝不代表你真正对这门课能有什么理解。
<strong>并且,全部依赖他人给你指明方向的人生已经结束了!</strong>
**并且,全部依赖他人给你指明方向的人生已经结束了!**
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcne9EK3xz8LHOXfM8w9ih5Ig.png)
![](https://cdn.xyxsw.site/boxcne9EK3xz8LHOXfM8w9ih5Ig.png)
你无法依赖大学里的老师还是家里的父母来为你指明所谓的方向,你的人生只属于你自己,你的道路也只能由你自己来思考。
考研的老师会更加重视你是否有能力与他进行利益交换,公司更在乎你是否可以为公司创造价值,想当然的思考已经无法跟上这个飞速运转的世界了。
# 大学现状
## 大学现状
在这里引用一段上海交通大学生存指南的一段话。
> 在当今流水线式的教育体制下,我们就像廉价的零件一样被生产出来。因为数量巨大,没人会对每一个人的教学质量负责。<br/>领导不会为你负责。对于一个争做世界一流大学的研究型学校,管好科研,管好实验室才是当务之急。<br/>相比之下,本科生教学显得无利可图。教授也不会为你负责。拉到足够的经费发表足够的论文,满足学院要求才是生存大计。<br/>要说管学生,也肯定先要管好自己实验室的硕士博士,而非那一百多人大课堂里的某个本科生。就算是科研任务不太重的一些任课教师,他们也不会为你负责——学不懂?那是因为你智力低,要么就是自己底下不用功。为什么跟你一个班上的某某某同学,人家就能懂?<br/>诚然,就算是老师上课说孟加拉语,一个班上也非常有可能冒出一两个翻翻书看看图就能学到八九不离十的同学(或者根本就是以前学过)。<br/>真正在课堂上口传心授的教学,其质量是不会有人过问的。教学评估会考察实验报告格式是否合格,出勤率是否够,但是绝对不会考察上百人的班上到底有几个听懂了的。<br/>试想一下,每个学院每个系有成百上千的学生,每人有着不同的思想、不同的目标、不同的知识背景、不同的接受力,我们怎么可能去指望一个统一的“教学培养计划”强制应用在每个人头上的时候,能够产生效果?好比说食堂师傅炒一大锅菜给上千人吃,我敢说我分到的那盘,不是炒糊就肯定得夹生。<br/>所谓“教学培养计划”,其科学性必须经过教育权威的论证。然而现实中塞给我们的推荐课表,却让人失望。且不深究选修课的分类、学分、毕业条件每年一个样,三年大变样,使得不少同学毕业前夕竞相奔走;甚至连两门相依赖课程的教学先后顺序都搞错过,这样的教学培养计划,实在让人难以信任
> 在当今流水线式的教育体制下,我们就像廉价的零件一样被生产出来。因为数量巨大,没人会对每一个人的教学质量负责。
>
> 领导不会为你负责。对于一个争做世界一流大学的研究型学校,管好科研,管好实验室才是当务之急。
>
> 相比之下,本科生教学显得无利可图。教授也不会为你负责。拉到足够的经费发表足够的论文,满足学院要求才是生存大计。
>
> 要说管学生,也肯定先要管好自己实验室的硕士博士,而非那一百多人大课堂里的某个本科生。就算是科研任务不太重的一些任课教师,他们也不会为你负责——学不懂?那是因为你智力低,要么就是自己底下不用功。为什么跟你一个班上的某某某同学,人家就能懂?
>
> 诚然,就算是老师上课说孟加拉语,一个班上也非常有可能冒出一两个翻翻书看看图就能学到八九不离十的同学(或者根本就是以前学过)。
>
> 真正在课堂上口传心授的教学,其质量是不会有人过问的。教学评估会考察实验报告格式是否合格,出勤率是否够,但是绝对不会考察上百人的班上到底有几个听懂了的。
>
> 试想一下,每个学院每个系有成百上千的学生,每人有着不同的思想、不同的目标、不同的知识背景、不同的接受力,我们怎么可能去指望一个统一的“教学培养计划”强制应用在每个人头上的时候,能够产生效果?好比说食堂师傅炒一大锅菜给上千人吃,我敢说我分到的那盘,不是炒糊就肯定得夹生。
>
> 所谓“教学培养计划”,其科学性必须经过教育权威的论证。然而现实中塞给我们的推荐课表,却让人失望。且不深究选修课的分类、学分、毕业条件每年一个样,三年大变样,使得不少同学毕业前夕竞相奔走;甚至连两门相依赖课程的教学先后顺序都搞错过,这样的教学培养计划,实在让人难以信任
诚然,杭电不可避免地也会受相应的“学术共同体”的影响,波及了包括但不限于竞赛,授课质量,氛围引导方面诸多的影响。
但是不可否认的,杭电也有不少优秀的老师愿意投身于教育事业当中。并且,杭电仍然有不少教育资源,可以满足一个人的所需所求。<del>(保研除外)</del>
但是不可否认的,杭电也有不少优秀的老师愿意投身于教育事业当中。并且,杭电仍然有不少教育资源,可以满足一个人的所需所求。~~(保研除外)~~

View File

@@ -1,19 +1,28 @@
# 2.2 优雅的使用工具
请大家记住使用工具的基本原则 <strong>你所感到不方便的!都有工具解决!</strong>
::: tip 🤗
如果你也有好的工具推荐,请补充喵~
:::
请大家记住使用工具的基本原则 **你所感到不方便的!都有工具解决!**
因此本小节的核心要义在于推荐一些有趣的有助于提高效率的小工具。
## 电脑软件及插件
因此本小节的核心要义在于推荐一些有趣的有助于提高效率的小工具
## 电脑便捷辅助插件
- [Everything](https://www.voidtools.com/zh-cn/downloads/) 电脑上的全局文件搜索 方便你找到不知道丢哪的文件
- [SpaceSniffer](http://www.uderzo.it/main_products/space_sniffer/download.html) 快速分析硬盘空间占用情况 解放储存,不解放大脑
- [IDM 及百度云脚本](https://greasyfork.org/zh-CN/scripts/436446-%E7%BD%91%E7%9B%98%E7%9B%B4%E9%93%BE%E4%B8%8B%E8%BD%BD%E5%8A%A9%E6%89%8B) <del>帮助你将百度云提速</del>(暂不可用)
- [Snipaste](https://zh.snipaste.com/) 全局截图工具,按 F1 键截图F3 键贴图,简单够用
- [eSearch](https://esearch.vercel.app/) 全局截图工具,优化了文字识别功能,可个性化,支持全平台
- [ShareX](https://esearch.vercel.app/) 全局截图工具,功能非常强大,高度可个性化,仅支持 Win
- [IDM](https://www.internetdownloadmanager.com/) :好用的多线程下载器(付费的),想要免费的话可以搜一下绿色版之类的。(推荐设置线程数为 CPU 核心数的 2 倍,比如 8 核心的 CPU 设置线程数为 16
- [XDM](https://github.com/subhra74/xdm) IDM 的跨平台版本。
- [uTools](https://www.u.tools/) :自由组合插件集(最好用的是 Alt+Space 搜索功能<del>和 PowerToys 二选一</del>)非常强大,比如安装 fileshare 可以在局域网共享超大文件,而且是跨平台的。
- [PowerToys](https://github.com/microsoft/PowerToys) :微软官方出品包含诸多功能,解决 windows 下一些小痛点。
- [Connect to Work or Games from Anywhere | Parsec](https://parsec.app/) :串流小工具,简单来说你就是可以在手机上玩电脑了,远程操作,极致体验<del>(也可以玩游戏)</del>
- [VMware workstation](../3.%E7%BC%96%E7%A8%8B%E6%80%9D%E7%BB%B4%E4%BD%93%E7%B3%BB%E6%9E%84%E5%BB%BA/3.Y.1VMware%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E5%AE%89%E8%A3%85Ubuntu22.04%E7%B3%BB%E7%BB%9F.md):虚拟机就用它!但是最好自己找找盗版,正版要钱。
- [uTools](https://www.u.tools/) :自由组合插件集(最好用的是 Alt+Space 搜索功能)非常强大,比如安装 fileshare 可以在局域网共享超大文件,而且是跨平台的。
- [PowerToys](https://github.com/microsoft/PowerToys) :微软官方出品包含诸多功能,解决 windows 下一些小痛点。
- [Connect to Work or Games from Anywhere | Parsec](https://parsec.app/) :串流小工具,简单来说你就是可以在手机上玩电脑了,远程操作,极致体验~~(也可以玩游戏)~~
- [VMware workstation](../3.%E7%BC%96%E7%A8%8B%E6%80%9D%E7%BB%B4%E4%BD%93%E7%B3%BB%E6%9E%84%E5%BB%BA/3.Y.3VMware%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E5%AE%89%E8%A3%85Ubuntu22.04%E7%B3%BB%E7%BB%9F.md):虚拟机就用它!但是最好自己找找盗版,正版要钱。
- [cloc](https://github.com/AlDanial/cloc): 统计代码行数(空白行,注释行,代码行)的小工具
- mv & cp 命令显示进度条: 在复制大文件的时候非常友好,可以通过以下脚本安装
- mv & cp 命令显示进度条在复制大文件的时候非常友好,可以通过以下脚本安装Linux 系统)
```bash
#!/bin/bash
@@ -29,7 +38,7 @@ wget http://ftp.gnu.org/gnu/coreutils/coreutils-8.32.tar.xz
tar -xJf coreutils-8.32.tar.xz
cd coreutils-8.32/
# Download patch
wget https://raw.githubusercontent.com/jarun/advcpmv/master/advcpmv-0.8-8.32.patch
wget https://ghproxy.com/https://raw.githubusercontent.com/jarun/advcpmv/master/advcpmv-0.8-8.32.patch
# Patching display with process bar
patch -p1 -i advcpmv-0.8-8.32.patch
# Compile then install
@@ -44,12 +53,17 @@ rm coreutils-8.32 coreutils-8.32.tar.xz
```
## 笔记工具
- [Typora](https://typora.io/) 付费的,<del>你可以去并夕夕啊淘宝啊花个不多于 5 块钱的钱买盗版 😋,</del> 正版 $14.99 ),真的好用,感觉没有 Markdown 编辑器能好用过 Typora🤥
- [MarkText](https://github.com/marktext/marktext) 费的 平替 Typora (?)感觉不太好用 😤
- [Typora](https://typora.io/) 费的~~你可以去并夕夕啊淘宝啊花个不多于 5 块钱的钱买盗版 😋~~,(正版 $14.99),真的好用,感觉没有 Markdown 编辑器能好用过 Typora🤥。
- [MarkText](https://github.com/marktext/marktext) 免费的,平替 Typora。
- [MiaoYan](https://github.com/tw93/MiaoYan) 仅支持 apple界面挺清爽。
- [思源笔记](https://b3log.org/siyuan/) 一个国产开源的笔记/知识库软件,优势是 本地化、双链、Markdown 语法,与 Obsidian 定位相似,但 Geek 成分和自定义空间相对更高
- [Zotero](https://www.zotero.org/):协助文献阅读还有笔记,支持与平板同传(同时他是开源的,所以可以添加一些插件)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnO1PEsVd4KY7reeU64spShf.jpg)
- [Notion](http://notion.so): 笔记终结者,非常强大,(设计理念被钉钉,飞书,我来非常抄袭)。在线就可以使用。唯一的缺点是可能需要科学上网。
- [Zotero](https://www.zotero.org/):协助文献阅读还有记录笔记,支持与平板同传(同时他是开源的,所以可以添加一些插件)
![](https://cdn.xyxsw.site/boxcnO1PEsVd4KY7reeU64spShf.jpg)
- [Notion](http://notion.so): 笔记终结者,非常强大,(设计理念被钉钉,飞书,我来非常抄袭)。在线就可以使用。
## 文献辅助阅读工具
- [知云文献翻译](https://www.zhiyunwenxian.cn/):可以有效帮助你翻译论文和文章甚至英文书籍
@@ -57,8 +71,8 @@ rm coreutils-8.32 coreutils-8.32.tar.xz
## 浏览器插件
- [沉浸式翻译](https://immersive-translate.owenyoung.com/installation):中英文对照翻译,可以给你英文下面写一小行中文翻译(里面免费的 api 只有谷歌,必应,腾讯,不过够了,也可以自行配置其他 api
- (你真的不玩原神吗)来试试这款原神浏览器插件 [派蒙 paimon](https://github.com/daidr/paimon-webext) 可以实时显示你的树脂,委托,派遣等情况提示。
- [沉浸式翻译](https://immersivetranslate.com/docs/installation/):中英文对照翻译,可以给你英文下面写一小行中文翻译(里面免费的 api 只有谷歌,必应,腾讯,不过够了,也可以自行配置其他 api
- (你真的不玩原神吗)来试试这款原神浏览器插件 [派蒙 paimon](https://github.com/daidr/paimon-webext) :可以实时显示你的树脂,委托,派遣等情况提示。
- [wappalyzer](https://www.wappalyzer.com/):如果你是个 web 仔,这个插件可以帮你检测网页所用的前后端技术栈。
- [FeHelper--Web 前端助手](https://github.com/zxlie/FeHelper):十几个小工具的集合,包括 base64 离线解码等。
- [darkreader](https://github.com/darkreader/darkreader):适应网页的暗色模式,夜深人静冲浪更爽

View File

@@ -1,12 +1,12 @@
# 2.3.1 阅读文档(B 百度爬)
# 2.3.1 阅读文档(百度爬)
# 查找教程
## 查找教程
一般帮助我们快速入门的最好的教程是在官网上的。
比如 Pytorch 的官方文档(甚至有中文版哦)。
同时,在 Youtube 和 B 站 上的不少资料也值得称道。
同时,在 Youtube 和 B 站上的不少资料也值得称道。
我不建议各位看黑马程序员,尚硅谷这种培训班的教程,太过细致反而有些本末倒置。
@@ -14,7 +14,7 @@
不要用百度百科!太多错误了!
# 查找资料
## 查找资料
你应该使用下表中推荐的网站:
@@ -24,7 +24,7 @@
- 通常来说, 英文维基百科比中文维基百科和百度百科包含更丰富的内容。
- 一些中文论坛内大家互相抄,很有可能你阅读了很久都没有找到正确的答案,并且英文社区内的内容远远比中文的要好。
# 英文阅读
## 英文阅读
随着科学技术的发展, 在国际学术交流中使用英语已经成为常态: 顶尖的论文无一不使用英文来书写, 在国际上公认的计算机领域经典书籍也是使用英文编著。
@@ -38,10 +38,16 @@
当然也有一些巧妙地方法帮助大家进行阅读,比如知云文献翻译,不要依赖这类软件!
# 科学上网
## 合理使用代理服务
学会科学上网是非常重要的一步哦
学会合理使用代理服务是非常重要的一步哦
机场无法给大家推荐,但是梯子经常用的无非就是 clash, ssr, v2ray
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="m8.85 15.65l8.9-2.35q.375-.1.563-.463t.087-.737q-.1-.375-.437-.562t-.713-.088l-2.45.65l-4-3.75l-1.4.35l2.4 4.2l-2.4.6l-1.25-.95l-.95.25l1.65 2.85ZM20 20H4q-.825 0-1.413-.588T2 18v-4q.825 0 1.413-.588T4 12q0-.825-.588-1.413T2 10V6q0-.825.588-1.413T4 4h16q.825 0 1.413.588T22 6v12q0 .825-.588 1.413T20 20Zm0-2V6H4v2.55q.925.55 1.463 1.463T6 12q0 1.075-.537 1.988T4 15.45V18h16Zm-8-6Z"/></svg>无法给大家推荐,但是<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M5.95 21q-.475 0-.75-.388t-.15-.837L9.5 3.7q.1-.325.35-.512T10.425 3q.5 0 .775.388t.15.837L10.85 6h5.625l.625-2.3q.1-.325.363-.512T18.05 3q.475 0 .75.388t.15.837L14.5 20.3q-.1.325-.35.513t-.575.187q-.5 0-.775-.388t-.15-.837l.5-1.775H7.525L6.9 20.3q-.1.325-.363.513T5.95 21Zm3.525-10h5.6l.825-3h-5.6l-.825 3ZM8.1 16h5.6l.825-3h-5.6L8.1 16Z"/></svg>经常用的无非就是 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 48 48"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M27.19 42.5a89.044 89.044 0 0 1-14.681-1.573s1.431-28.554 5.411-35.39c-.13-.297 2.992 1.212 4.422 6.266a25.557 25.557 0 0 1 4.847-.47"/><ellipse cx="21.24" cy="20.309" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" rx="1.671" ry="2.13"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M27.19 42.5a89.044 89.044 0 0 0 14.681-1.573s-1.431-28.554-5.413-35.39c.03-.2-3.59 1.755-4.421 6.266a25.558 25.558 0 0 0-4.848-.47"/><ellipse cx="33.14" cy="20.309" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" rx="1.671" ry="2.13"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="5.714" d="M12.508 40.927c-1.93-.327-4.948-.31-6.04-3.487c-1.067-3.107.438-6.67 3.742-7.045m15.253-4.008a1.467 1.467 0 0 0 1.473-1.472"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="5.714" d="M28.41 26.387a1.467 1.467 0 0 1-1.474-1.472"/></svg>, <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 48 48"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M40.53 6.78a.26.26 0 0 1 .22.31l-6.39 28.17a.22.22 0 0 1-.28.16l-13.64-4.3a.52.52 0 0 1-.25-.83l11.6-14.17l-.11-.12l-16.07 13.84a.58.58 0 0 1-.54.09l-11.2-4.41a.21.21 0 0 1 0-.38L40.39 6.81h.14Zm-20.4 27l6.69-.69l-6.41 8a.28.28 0 0 1-.5-.18l.17-10.47"/></svg>
如果不知道怎么办,可以求助(找学长)
<style module>
svg {
display: inline-block;
}
</style>

View File

@@ -2,11 +2,11 @@
请克服对论文英文的恐惧,适当的利用翻译软件。
<del>由于笔者只阅读过 CV 领域和</del><del>NLP</del><del>领域的一些文章,且阅读量并不算太高,故对论文的理解不仅有限且仅限于该领域内的论文风格和内容技巧,望读者见谅。</del>
~~由于笔者只阅读过 CV 领域和NLP领域的一些文章,且阅读量并不算太高,故对论文的理解不仅有限且仅限于该领域内的论文风格和内容技巧,望读者见谅。~~
## 论文的一般结构
### 1.title(标题)
### 1. title(标题)
首先是标题部分。
@@ -16,19 +16,23 @@
论文作者会在标题下面指出,当我们的论文阅读量到一定程度之后可以关注一下作者。当我们在关注或研究某一个领域时,该领域的几篇重要论文读下来我们就可以知道哪个作者在该领域较为活跃,谁提出了 Backbone ,谁在挖坑(填坑)。可以通过作者进而检索到你感兴趣的工作或判断论文写作质量。
### 2.abstract(摘要)
### 2. abstract(摘要)
Abstract 是论文中一篇具有独立性的短文,用简单、明确、易懂、精辟的语言对全文内容加以概括,提取论文的主要信息。作者的观点、论文的主要内容、研究成果、独到的见解,这些都会在摘要中体现出来,是需要重点阅读的地方。
摘要在资料交流方面承担着至关重要的作用。摘要会收录到大型资料库中并为读者提供信息,因此我们可以通过摘要索引查找论文。
摘要的四要素:目的、方法、结果和结论称为摘要的四要素。
1目的指出研究的范围、目的、重要性、任务和前提条件不是主题的简单重复。
2方法根据研究的主要内容和发现的问题说明在这个过程中都做了哪些工作。(摘要中的方法不会太过详细,一般只会给出一个名词)
3结果陈述研究之后重要的新发现、新成果及价值包括通过调研、实验、观察取得的数据和结果并剖析其不理想的局限部分。
4结论通过对这个课题的研究所得出的重要结论包括从中取得证实的正确观点进行分析研究比较预测其在实际生活中运用的意义理论与实际相结合的价值。
### 3.introduction(导言)
### 3. introduction(导言)
Introduction 主要是对整篇论文的一个介绍,读者看完 introduction 后就知道论文的几乎所有工作。
@@ -36,19 +40,19 @@ Introduction 会说明论文的主题、范围和研究目的。
然后阐明研究的起因、背景及相关领域简要历史回顾。(前人做了哪些工作、哪些尚未解决、目前进展到何种程度等)这一部分不同的论文情况不同,有些论文会单独拿出来作为一部分(related work)当我们刚进入到某一个领域时我们可以通过这一部分了解该领域的大致研究风格和该篇论文的研究路径get 到作者的研究思路(论文的这个课题存在有着哪些问题以及所面临怎样的挑战,发现前人工作的缺陷以及在此基础上的改进),有时可能会对我们的工作有启发。当然,如果我们对这一领域足够了解,可以不需要看这一部分,研究思路也可以在论文的方法部分自行体会。
### 4.method(提出的算法)
### 4. method(提出的算法)
此处为文章主体,详细介绍了他是怎么做的,<del>如果需要复现的话需要仔细阅读这一部分</del>,无论复现与否都需要详细阅读,理解具体操作与作者的理论并尽可能将二者结合<del>(该领域的某些方面可解释性并不强)。</del>读者不仅可以从该部分具体理解论文工作,还可以从中发现与前人工作的不同,并从中提出进一步改进。
此处为文章主体,详细介绍了他是怎么做的,~~如果需要复现的话需要仔细阅读这一部分~~,无论复现与否都需要详细阅读,理解具体操作与作者的理论并尽可能将二者结合~~(该领域的某些方面可解释性并不强)~~。读者不仅可以从该部分具体理解论文工作,还可以从中发现与前人工作的不同,并从中提出进一步改进。
### 5.experiment(实验)
### 5. experiment(实验)
<del>一般情况为介绍我为什么很牛逼,这里一般可以跳过如果不写文章的话</del>
~~一般情况为介绍我为什么很牛逼,这里一般可以跳过如果不写文章的话~~
该部分一般会晒出工作的效果,我们可以从中更直观的体会工作的改进,甚至可以根据结果直接推断结果好坏的某些原因<del>(不过一般论文中的图片当然都会放效果很好的以便作者吹逼,真想看效果建议复现工作)</del>,大胆并合理的假设推理也是科研工作中不可缺少的一个能力。
该部分一般会晒出工作的效果,我们可以从中更直观的体会工作的改进,甚至可以根据结果直接推断结果好坏的某些原因~~(不过一般论文中的图片当然都会放效果很好的以便作者吹逼,真想看效果建议复现工作)~~,大胆并合理的假设推理也是科研工作中不可缺少的一个能力。
### 6.conclusion(结论)
### 6. conclusion(结论)
<del>Conclusion 结论部分,一般阅读完开头直接阅读结尾,就基本清楚文章脉络结构和思考方案了</del>
~~Conclusion 结论部分,一般阅读完开头直接阅读结尾,就基本清楚文章脉络结构和思考方案了~~
结论和摘要的内容基本相似,但某些论文的结论中可能还会指出对该工作的不足之处,还有该领域内对该工作的一些期望(挖坑)。
@@ -56,19 +60,21 @@ Introduction 会说明论文的主题、范围和研究目的。
视频地址: [如何读论文【论文精读】](https://www.bilibili.com/video/BV1H44y1t75x)
### 第一遍(海选)
<Bilibili bvid='BV1H44y1t75x'/>
### 第一遍(海选)
阅读标题、摘要、结论。花费十几分钟时间了解论文是否适合你的研究方向。
看完之后可以再看一看方法和实验部分重要的图和表,进而判断这篇论文是否适合自己,是否和自己当前在做的工作相似。
### 第二遍(大致把握)
### 第二遍(大致把握)
确定论文值得读之后,快速将整个论文过一遍,不需要知道所有的细节,先尝试去理解论文中重要的图和表,知道每一个部分在干什么,圈出比较重要的相关文献。
若到此为止:知道它解决什么问题,结果怎么样,大概用了什么方法,但是觉得文章很难看不太懂,可以去读他们之前引用的那些文章,读完之后再回头读这篇文章。
### 第三遍(重点研读)
### 第三遍(重点研读)
第三遍是最详细的一遍,当我们在读第三遍时通常意味着我们对该论文的工作很感兴趣了,这时我们需要力争做到知道每一段和每一句都在说什么、干什么。基本了解整个文章的细节,在之后基于他做研究,或者在之后提到它的时候,可以详详细细的复述一遍。

View File

@@ -1,6 +1,6 @@
# 2.3.3 优秀的开源社区
# 什么是开源?
## 什么是开源?
开源是源代码可以任意获取的计算机软件,这种软件的著作权持有人在软件协议的规定下保留一部分权利并允许用户学习、修改以及以任何目的向任何人分发该软件。
@@ -10,7 +10,7 @@
这里面有非常多有趣的历史故事以及各种渊源,感兴趣的同学可以自行了解一下
# 灵活使用开源社区
## 灵活使用开源社区
开源社区有时候是我们大伙学习一个新技术,查找某一个资料非常好的一种方式。
@@ -22,7 +22,7 @@
如果说国外的
[GitHub: Where the world builds software](https://github.com/)最好科学上网)(全世界最大的开源社区)
[GitHub: Where the world builds software](https://github.com/)(全世界最大的开源社区)
在本章内容 /3.编程思维体系构建/3.5git与github 中详细介绍了github和git的使用方法大家可以参考一下
@@ -34,94 +34,61 @@ awesome (你想学的东西)
例如 awesome C
# 开源的意义
## 开源的意义
本章内容节选自Datawhale 5位成员在AI TIME的分享《清华、北大、上交大、哈工大、中山大学5位同学眼中的开源》。
## Z世代的开源新态度
杨毅远王琦与江季作为《Easy RL: 强化学习教程》的作者,他们有着丰富的开源经历与感受。
杨毅远:开源收获的是一个正向反馈
在互联网上开源自己的论文代码、项目代码以及学习心得等内容,也有助于和他人沟通交流,收获的也是一个正向反馈。针对问题普通人如何实现开源,杨毅远认为还是要先拥抱开源,不必操之过急,开源工作需要是有意义的工作,是一个漫长的工作。
王琦:开源的过程虽然会占用自己的一部分时间,但这却是一个幸福的烦恼。
论文末尾大多会附上代码地址即代码开源。大家在看到论文代码开源的情况下会认为这篇论文能够复现的可能性比较大。虽然在将开源项目发布到GitHub之后给他人问题答复的过程可能会占用自己的一部分时间但这可以算是一个幸福的烦恼。
江季:敢于开源的人也是一个乐于分享,心态积极的人。
互联网上的开源是需要勇气的,毕竟开源后的代码要在互联网上面临网友们的考验。江季对于开源的领域也有自己独到的见解,他以春秋战国时期的百家争鸣为例,阐述了无论是对于工科生还是文科生,开源这件事都是很适用的。
张文涛:能够与志同道合的人交流,是开源过程中至关重要的一环。
开源不是一个瞬间,而是需要持续地去做,无论是主动还是被动。将项目发布到网络上只是一个起点,之后反复与他人交流和解决问题,进而对项目进行不断的修正。
陈安东:要像种一棵树一样等到自己的开源工作开花结果。
开源可以分为三点:首先是要知道自己想要什么;第二点是做开源一定要有始有终,只有完整的开源工作才能被大家使用和学习,完整的工作才能在之后有优化迭代的空间;第三是要有一个”开源是一个长期的过程”这样的心态。
## 作为年轻一代,我们眼中的企业开源
王琦:企业的目的可能是先通过开源抢占市场,后续再通过推行定制化的服务来盈利。
陈安东:开源是一种企业与市场自我革命的做法,这种革命能够促进技术的发展,最终为用户带来好处。
一个行业的开源企业对传统1对1收费的市场是一个不小的冲击因为这个市场份额也就随着这家免费的开源企业而不断减小。但是由于开源带来的技术分享反而使市场更加集中与优质化技术也随着开源而更快速的迭代从而产生了更好用的产品。
张文涛:开源有利于提升产品的影响力
虽然公司在做开源之前不一定有明确商业目的,但是可能在开源过程中发现一些可盈利的点来开发出其产品线。然后,企业可以将这块收入的一部分反馈到开源的过程之中来增加产品的影响力。
杨毅远:开源不失为一种提高公司知名度和用户信任感的方式
如果是一家中小型的创业公司,是否可以把自己核心的一部分开源出来?这样不失为一种提高公司知名度和用户信任感的方式。此外,当把实验代码开源到网络上之后,人们也希望有其他同领域的专家、研究人员可以一起来滚动更新这个任务。
## 关于未来的开源,我们想说……
江季:开源是一个很有前景的领域,然而现在的开源文化还并不成熟,开源确实是仍然在路上。
开源目前仍然存在不够合格的现象,比如说某些人的开源工作难以复现。开源是一个很有前景的领域,尤其是在促进学术界发展上。然而现在的开源文化还并不成熟,开源网站中占据大部分篇幅的还是广告,并没有形成知识分享的模式,开源确实是仍然在路上。
张文涛:开源的形式丰富多样,暂时不必思考太多,可以先和志同道合的人一起前进。
王琦:三体人的先进在于一代又一代的持续知识共享,我们可以先模仿、学习他人的项目。
我们如今做的东西,可能在历史长河之中早已被他人做过。如果提前了解到这些,可以很大地提升我们的工作效率。如果想做一个优质的开源项目,我们可以先模仿、学习他人的项目。
陈安东:开源应该是一个特别酷的东西,要敢于让别人看到自己的工作。
如今的开源还远远不够,大多数人还停留在在闭门造车的阶段。鼓励大家将自己的项目分享出来让大家来一起参与,接受大家的评价,彼此交流与指出问题,这样不但可以让开源工作更好,也可以让参与开源的大家收获满满。

View File

@@ -12,6 +12,8 @@ Typora
看看下面教程
https://www.markdown.xyz/
https://www.markdown.xyz
以及这个
https://castel.dev/post/lecture-notes-1/
https://castel.dev/post/lecture-notes-1

View File

@@ -2,11 +2,12 @@
作为一名理工科学生,也许英语并不是你的强势,但往往学习又难以避开英语。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/G6zAbGrTKoBLsfxhmvHcUBVynpc.png)
![](https://cdn.xyxsw.site/G6zAbGrTKoBLsfxhmvHcUBVynpc.png)
下面提供一些英语阅读的方法:
1. <strong>学好英语(顺便过四六级)</strong>
2. 文档阅读:使用浏览器插件,例如:[沙拉查词](https://saladict.crimx.com/)、[划词翻译](https://hcfy.app/)
1. **学好英语(顺便过四六级)**
2. 文档阅读:使用浏览器插件,例如:[沙拉查词](https://saladict.crimx.com/)、[划词翻译](https://hcfy.app/)、[沉浸式翻译](https://immersivetranslate.com/docs/)、[DeepL翻译](https://www.deepl.com/zh/app/)
3. Youtube 等视频网站的双语字幕 [languagereactor](https://www.languagereactor.com/)。
4. 实用翻译软件[复制即翻译](https://copytranslator.github.io/)。
5. ~~Galgame 翻译 [LunaTranslator](https://github.com/HIllya51/LunaTranslator)~~

View File

@@ -0,0 +1,15 @@
# 2.1.6学会使用AI辅助学习
在过去AI取代人类似乎一直是一件遥远的事情但在 2022 年末OpenAI 的 ChatGPT 发布后在全球引发了一场 AI 热潮ChatGPT 所表现出来的能力让我们思考在不久的未来我们真的会被AI取代吗
在知识储备上,我们人类在 AI 面前绝不占优势,就比如 ChatGPT 是几乎使用了绝大多数西方互联网的优质回答而训练出来的想要在知识储备量战胜AI已经成了天方夜谭但大家也不要为不知道一些知识而焦虑我很欣赏南京大学的蒋炎岩教授说的一句话“大佬和小白的差距并不是知识量的差距而是大佬知道如何问出好的问题搜索引擎会告诉你答案或许未来还可以问 AI ”
假如你已经玩过 ChatGPT ,你会发现它还远没有到真正取代人类的地步,而是它的出现已经能够使教育以及学习方式发生巨大变革。接下去我会给你们一些小建议:
- 如果你希望完成一件事但却不知道怎么做,你可以问搜索引擎 (PS:远离百度! 通常会得到 StackOverflow 上的答案),或是直接问 ChatGPT不过要小心人工智能现在还经常一本正经胡说八道。
- 问出合适的问题,就像你问一个大佬,假如你给出的 Prompt 非常宽泛而模糊无论是谁都没法保障给出的答案是你想要的。比如你问“如何学好数学”你可能会得到“多做题”这样的答案但这并不是你想要的。你应该问“如何学好导数”这样你就能得到更加精准的答案。问ChatGPT也是同样的道理假如你给了它一个非常宽泛的 Prompt ,它也只能给你一个模糊而无用的回答,假如给它的 Prompt 非常准确,那么你得到一个优质的回答的概率也会更高。
- 有时候遇到一些你不愿意从头读到尾的手册这时候去问ChatGPT是一个合适的选择在一个手册里可能你需要的只是其中的一小段但是手册却有几十页此时ChatGPT的优势就体现出来了它会根据你给的 Prompt 从手册中总结你需要的知识告诉你这极大地降低了检索知识的成本所以我觉得ChatGPT更像一个加强版搜索引擎。
- 向AI获取知识在现在的很多时候AI对于知识的掌控和讲解的逻辑性甚至超过了相当一大部分老师或许去听3节长课甚至不如向ChatGPT问几个问题学到的知识更多或许未来的课堂可以变成老师下发一张写着问题的卡片我们只需要发给ChatGPT通过它的回答来学习
- 还有就是在大学你会遇到非常多非常无趣的报告甚至有些报告需要查重没人愿意写这时候ChatGPT就成为了拯救你的时间的利器直接告诉它报告的要求同时限定个数和字数往往它能给出能混出相对高分的优质低信息熵报告当然这适合的是一些水课报告专业课报告别这么搞专业课报告最好用它做来辅助你的写作而不是直接抄袭。
> PS. 不论ChatGPT还是一些别的AI它们的回答都不是绝对准确的使用的时候要带有自己的思考不要盲目相信AI的指示把AI作为你的帮手这能极大提高你的学习效率。

View File

@@ -9,22 +9,27 @@ author:zzm 邮箱 1264517821@qq.com
但是首先各位需要了解几个名词
::: danger 名词提醒
# RTFM
<div style="font-size: 2rem;line-height: 2;">RTFM</div>
Read the f**friendly manual
# STFW
:::
::: danger 名词提醒
<div style="font-size: 2rem;line-height: 2;">STFW</div>
Search the "friendly" website
:::
# 为什么不能直接告诉我?
## 为什么不能直接告诉我?
因为本讲义的目的除了让你学会知识以外,更重要的目的是教给你如何当一个合格的大学生。
一个合格的大学生理应具备独立解决问题的能力。
<strong>并且这是无论是学术界还是工业界都非常重视的基本素养</strong>
**并且这是无论是学术界还是工业界都非常重视的基本素养**
当遇到问题不是赶紧找个大神帮我,而是"我来试试 STFW 和 RTFM, 看能不能自己解决".
@@ -34,17 +39,16 @@ Search the "friendly" website
这也是我们希望大伙能获得的能力,如果把全部信息都塞上去难免有些揠苗助长。
况且现在还有GPT来辅助你去解决问题大大降低了学习的难度不过大家需要谨慎考虑的是现在的机器也会一本正经的胡说八道
况且现在还有ChatGPT来辅助你去解决问题大大降低了学习的难度不过大家需要谨慎考虑的是现在的机器也会一本正经的胡说八道
:::
# 如果真的不知道怎么解决怎么办?
## 如果真的不知道怎么解决怎么办?
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnSmy1oqFO1glYIYGRZ9NhEb.jpg)
![](https://cdn.xyxsw.site/boxcnSmy1oqFO1glYIYGRZ9NhEb.jpg)
来细看看本章节的内容吧!
# 参考内容 上海交大生存指南
## 参考内容 上海交大生存指南
[https://survivesjtu.gitbook.io/survivesjtumanual/](https://survivesjtu.gitbook.io/survivesjtumanual/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

View File

@@ -1,19 +1,19 @@
# 补充:为什么不要用百度
相信大家都用过百度来搜索一些非技术问题, 而且一般很容易找到答案. 但随着问题技术含量的提高, 百度的搜索结果会变得越来越不靠谱. 坚持使用百度搜索技术问题, 你将很有可能会碰到以下情况之一:
相信大家都用过百度来搜索一些非技术问题而且一般很容易找到答案 但随着问题技术含量的提高百度的搜索结果会变得越来越不靠谱 坚持使用百度搜索技术问题你将很有可能会碰到以下情况之一
- 搜不到相关结果, 你感到挫败
- 搜到看似相关的结果, 但无法解决问题, 你在感到挫败之余, 也发现自己浪费了不少时间
- 你搜到了解决问题的方案, 但没有发现原因分析, 结果你不知道这个问题背后的细节
- 搜不到相关结果你感到挫败
- 搜到看似相关的结果但无法解决问题你在感到挫败之余也发现自己浪费了不少时间
- 你搜到了解决问题的方案但没有发现原因分析结果你不知道这个问题背后的细节
你可能会觉得"可以解决问题就行, 不需要了解问题背后的细节". 但对于一些问题(例如编程问题), 你了解这些细节就相当于学到了新的知识, 所以你应该去了解这些细节, 让自己懂得更多.
你可能会觉得"可以解决问题就行不需要了解问题背后的细节" 但对于一些问题(例如编程问题)你了解这些细节就相当于学到了新的知识所以你应该去了解这些细节让自己懂得更多
如果谷歌能以更高的概率提供可以解决问题的方案, 并且带有原因分析, 你应该没有理由使用百度来搜索技术问题. 如果你仍然坚持使用百度, 原因就只有一个: 你不想主动去成长.
如果谷歌能以更高的概率提供可以解决问题的方案并且带有原因分析你应该没有理由使用百度来搜索技术问题 如果你仍然坚持使用百度原因就只有一个 你不想主动去成长
你或许会觉得翻阅手册太麻烦了, 所以可能会在百度上随便搜一篇博客来尝试寻找解决方案. 但是, 你需要明确以下几点:
你或许会觉得翻阅手册太麻烦了所以可能会在百度上随便搜一篇博客来尝试寻找解决方案 但是你需要明确以下几点
- 你搜到的博客可能也是转载别人的, 有可能有坑
- 博主只是分享了他的经历, 有些说法也不一定准确
- 搜到了相关内容, 也不一定会有全面的描述
- 你搜到的博客可能也是转载别人的有可能有坑
- 博主只是分享了他的经历有些说法也不一定准确
- 搜到了相关内容也不一定会有全面的描述
最重要的是, 当你尝试了上述方法而又无法解决问题的时候, 你需要明确"我刚才只是在尝试走捷径, 看来我需要试试 RTFM 了".
最重要的是当你尝试了上述方法而又无法解决问题的时候你需要明确"我刚才只是在尝试走捷径看来我需要试试 RTFM 了"

View File

@@ -13,7 +13,7 @@
### 这篇讲义讲什么
- 首先,如上文所述,如何轻松地利用本章乃至整个讲义
- 在第一点的基础上,引申出我自己归纳的<strong>编程入门之“道”</strong>
- 在第一点的基础上,引申出我自己归纳的**编程入门之“道”**
### 请随意喷这篇讲义
@@ -28,7 +28,7 @@
1. 这里的文章的最大的作用是帮你打开信息壁垒,告诉你编程的世界有哪些东西,可以去学什么。
2. 把讲义当成字典来用。很多文章并不是完全对新人友好的,你现在不需要看懂,甚至可能不需要看。你只要大概记下有这么个概念和工具,当下次要用到的时候,再查阅、再仔细学习就好。
简单来说就是,<strong>抱着平和的心态,随便看看</strong>,知道这一章都讲了哪些东西,看完有个印象就好,然后常回家看看。
简单来说就是,**抱着平和的心态,随便看看**,知道这一章都讲了哪些东西,看完有个印象就好,然后常回家看看。
技术细节本身永远都不是最重要的,重要的是思想和方法,如何快速掌握一门技术。
@@ -38,7 +38,7 @@
这是我的第一个也是最重要的建议。
无论是学一门语言,还是学一个工具:<strong>尽可能地先用最短的时间搞懂这个东西是做什么的,然后以最快的方式把它 “run”起来。</strong>
无论是学一门语言,还是学一个工具:**尽可能地先用最短的时间搞懂这个东西是做什么的然后以最快的方式把它“run”起来。**
当你已经能跑起一个语言、一个工具的最简单的示例的时候,再去花时间慢慢了解背后的复杂的内容,再去拓展即可。先用起来,跑起来,带着问题去翻资料。
@@ -58,7 +58,7 @@
那么该怎么学呢?
<strong>先简单地会一样东西的最核心的部分,再去找一个实际的编程场景、编程任务、项目。你会在完成这个项目中遇到各种各样的问题,无论是遗漏了知识点还是压根没思路, 这时候不断地用搜索引擎来学习。( </strong>[2.3 高效的信息检索](../2.%E9%AB%98%E6%95%88%E5%AD%A6%E4%B9%A0/2.3%E9%AB%98%E6%95%88%E7%9A%84%E4%BF%A1%E6%81%AF%E6%A3%80%E7%B4%A2.md)<strong></strong>
**先简单地会一样东西的最核心的部分,再去找一个实际的编程场景、编程任务、项目。你会在完成这个项目中遇到各种各样的问题,无论是遗漏了知识点还是压根没思路,这时候不断地用搜索引擎来学习。( **[2.3 高效的信息检索](../2.%E9%AB%98%E6%95%88%E5%AD%A6%E4%B9%A0/2.3%E9%AB%98%E6%95%88%E7%9A%84%E4%BF%A1%E6%81%AF%E6%A3%80%E7%B4%A2.md)****
举个例子:你想做一个小程序,来检测某电影院的电影预售。程序大概要做到不断刷新网页,一检测到这个电影预售了,就马上发短信给自己手机(或者直接帮你抢)
@@ -85,7 +85,7 @@
刚开始你可能什么都不会,什么地方都被阻塞,但当你把坑踩遍了。就发现,哎嘿,不好意思,这玩意我怎么又会!
<strong>所以让我们基于这个“任务驱动”,再看看本章的内容。这些内容大多看了就忘,因为细节非常多,而且并不一定能解决你手头上的问题。但这些文档,带你领进了新的领域的大门,让你的工具箱里多了一个可以解决问题的工具,以后用到了可以想起他们。并且,这些文章多是通俗的,且作者多是讲述了 ta 所认为的该语言/工具的最核心、最精华的部分,或者说第一次入门最需要学习的部分。</strong>
**所以让我们基于这个“任务驱动”,再看看本章的内容。这些内容大多看了就忘,因为细节非常多,而且并不一定能解决你手头上的问题。但这些文档,带你领进了新的领域的大门,让你的工具箱里多了一个可以解决问题的工具,以后用到了可以想起他们。并且,这些文章多是通俗的,且作者多是讲述了 ta 所认为的该语言/工具的最核心、最精华的部分,或者说第一次入门最需要学习的部分。**
## 圈子
@@ -101,7 +101,7 @@
1. 输入决定输出。开源的代码多是经过检验的牛逼的代码,通过多看看优雅的代码来提高编程能力,比自己无中生有简单地多。
2. 开源圈牛人多。无论是拓宽视野,还是在 issue 下的交流,还是别人给你的 review 建议,都能学到很多。你会在开源的过程中认识很多的人,很多大厂的人,说不定就是你以后的面试官。
3. 参与开源社区能极大地锻炼自己的编程能力,能给简历贴金
3. 参与开源社区能极大地锻炼自己的编程能力,能给简历贴金。
4. 开源是程序员的浪漫。
对于学生而言,可以参加一些仅面向学生开放的开源活动。一般会有一个主办方,然后有许多知名的开源社区报名。他们会罗列出一些有一定难度的任务,学生可以提交申请书,陈述如何完成这个任务。中选后会分配单独的导师来带你,还会发奖金给你,一般是大几千起步。推荐阅读这个系列的文章:[https://erdengk.github.io/gsoc-analyse/](https://erdengk.github.io/gsoc-analyse/)

View File

@@ -1,6 +1,6 @@
# 3.1 该使用哪个编辑器???
# 编辑器,编译器,集成开发环境
## 编辑器,编译器,集成开发环境
我们平时所说的程序是指双击后就可以直接运行的程序这样的程序被称为可执行程序Executable Program
@@ -12,7 +12,7 @@
(你也不想用一沓纸带写程序吧)
## 什么是编辑器
### 什么是编辑器
编辑器的概念很简单,百度百科上这么写道:
@@ -20,11 +20,11 @@
当然在这里我们主要讲的是代码编辑器,一个好的编辑器可以节省开发时间,提高工作效率,它们都能提供非常方便易用的开发环境。你可以用它们来编写代码,查看源文件和文档等,简化你的工作。以下是一些常用的代码编辑器,每个不同的编辑器都有不尽相同的目标用户群体。
- <em>Visual Studio Code</em> : 微软 VS 系列的新作品,适用于多平台的代码编辑器,其很好服从了轻量化 + 拓展的 Unix 思想,在整体快捷方便的同时具有极强的功能拓展空间,是值得首要推荐的编辑器。
- <em>Vim </em>: Vim 是从 vi 发展出来的一个文本编辑器,在程序员中被广泛使用,运行在 Linux 环境下。
- <em>GNU Emacs</em> : Emacs 是一个轻便、可扩展、免费的编辑器,它比其它的编辑器要更强大,是一个整合环境,或可称它为集成开发环境。它可以处理文字,图像,高亮语法,将代码更直观地展现给开发者。
- *Visual Studio Code* : 微软 VS 系列的新作品,适用于多平台的代码编辑器,其很好服从了轻量化 + 拓展的 Unix 思想,在整体快捷方便的同时具有极强的功能拓展空间,是值得首要推荐的编辑器。
- *Vim*: Vim 是从 vi 发展出来的一个文本编辑器,在程序员中被广泛使用,运行在 Linux 环境下。
- *GNU Emacs* : Emacs 是一个轻便、可扩展、免费的编辑器,它比其它的编辑器要更强大,是一个整合环境,或可称它为集成开发环境。它可以处理文字,图像,高亮语法,将代码更直观地展现给开发者。
## 什么是编译器
### 什么是编译器
C 语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于 CPUC 语言代码就是天书根本不认识CPU 只认识几百个二进制形式的指令。这就需要一个工具,将 C 语言代码转换成 CPU 能够识别的二进制指令,也就是将代码加工成 .exe 程序这个工具是一个特殊的软件叫做编译器Compiler
编译器能够识别代码中的词汇、句子以及各种特定的格式并将他们转换成计算机能够识别的二进制形式这个过程称为编译Compile
@@ -56,7 +56,7 @@ C 语言代码由固定的词汇按照固定的格式组织起来,简单直观
编译器可以 100% 保证你的代码从语法上讲是正确的,因为哪怕有一点小小的错误,编译也不能通过,编译器会告诉你哪里错了,便于你的更改。
## 什么是集成开发环境
### 什么是集成开发环境
实际开发中,除了编译器是必须的工具,我们往往还需要很多其他辅助软件,例如:
@@ -72,18 +72,18 @@ C 语言代码由固定的词汇按照固定的格式组织起来,简单直观
集成开发环境也是这个道理,只有编译器不方便,所以还要增加其他的辅助工具。
# 我的推荐
## 我的推荐
作为个人使用比较顺手的几款 IDE
Java: [JetBrains](https://www.jetbrains.com/zh-cn/idea/)[ IntelliJ ](https://www.jetbrains.com/zh-cn/idea/)[IDEA](https://www.jetbrains.com/zh-cn/idea/)
Java: [JetBrains](https://www.jetbrains.com/zh-cn/idea/)[IntelliJ](https://www.jetbrains.com/zh-cn/idea/)[IDEA](https://www.jetbrains.com/zh-cn/idea/)
C: Visual Studio(宇宙第一 IDE), [JetBrains](https://www.jetbrains.com/zh-cn/clion/)[ Clion](https://www.jetbrains.com/zh-cn/clion/), Visual Studio Code(编辑器 IDE 化需要额外配置)
C: [Visual Studio宇宙第一 IDE](https://visualstudio.microsoft.com/zh-hans/vs/) [JetBrains Clion](https://www.jetbrains.com/zh-cn/clion/)Visual Studio Code编辑器 IDE 化需要额外配置)
Python: [JetBrains](https://www.jetbrains.com/zh-cn/pycharm/)[ ](https://www.jetbrains.com/zh-cn/pycharm/)[P](https://www.jetbrains.com/zh-cn/pycharm/)[ycharm](https://www.jetbrains.com/zh-cn/pycharm/)
Python: [JetBrains Pycharm](https://www.jetbrains.com/zh-cn/pycharm/)
Vim 在附加篇章里有额外介绍
[JetBrains](https://www.cnblogs.com/Coline1/p/15229244.html)[白嫖指南](https://www.cnblogs.com/Coline1/p/15229244.html)
[JetBrains](https://www.cnblogs.com/Coline1/p/15229244.html)[白嫖指南](https://www.cnblogs.com/Coline1/p/15229244.html)
当然,适合你的才是最好的

View File

@@ -2,17 +2,17 @@
author:wenjing
先验条件:保证你可以在每天进行练习和学习此方面内容即使是假期也不能超过三天以上休息,如果你想验证一下这件事当然也可以,注意心态的保持很重要
先验条件:保证你可以在每天进行练习和学习此方面内容即使是假期也不能超过三天以上休息如果你想验证一下这件事当然也可以,注意心态的保持很重要
# 将时间花在 ACM 上值得吗?
## 将时间花在 ACM 上值得吗?
初入大学,摆脱了高中的种种束缚,同学们想必对大学生活有着种种幻想。或许有同学依旧保持着高中的思维,希望刷取高绩点,用好成绩谋求保研。或许也有同学只想将课程草草应付,去探索一些偏实践的方向以谋求一份好工作。
但无论你渴望从大学生活谋求何物,我认为做为一位计算机专业的学生投身于 ACM 算法竞赛学习都是值得,无论你是否得奖。
# ACM 能为我带来什么?
## ACM 能为我带来什么?
显然,做为一名计算机专业的学生,编程是一项必须掌握的技能。再次引用 Niklaus Emil Wirth 的一句话:<strong>程序=算法 + 数据结构。</strong>例如在大一开设的程序设计基础中,我们需要重点学习链表这一数据结构,熟悉运用分支与循环结构(勉强也算算法吧)。然而,在 ACM 中,这是基础到不值一提的事物,宛如空气与水一般基础。你们是否想过,花了大量课时学习的这些知识,其实小学生也可以学会(看看远处的小学编程补习班吧,家人们)那做为大学生去学习这些知识,是否应当得到一些不止于考试内容的知识呢?
显然,做为一名计算机专业的学生,编程是一项必须掌握的技能。再次引用 Niklaus Emil Wirth 的一句话:**程序=算法 + 数据结构。**例如在大一开设的程序设计基础中,我们需要重点学习链表这一数据结构,熟悉运用分支与循环结构(勉强也算算法吧)。然而,在 ACM 中,这是基础到不值一提的事物,宛如空气与水一般基础。你们是否想过,花了大量课时学习的这些知识,其实小学生也可以学会(看看远处的小学编程补习班吧,家人们)那做为大学生去学习这些知识,是否应当得到一些不止于考试内容的知识呢?
我认为有两个方向,一是我们去学习一些更底层的逻辑与原理,此外就是学习如何更好的利用链表,实现一些别的数据结构做不到的事情,我认为 ACM 可以极大的提升我们对后者的理解。
@@ -24,7 +24,7 @@ author:wenjing
③ 假如你有幸活过筛选并且获得比赛机会并且得奖恭喜你你的绩点将被画上浓墨重彩的一笔。做为大学顶尖赛事ACM 的奖项可以直接在你的最终绩点上加分(铜 0.5,银 1.0,金 1.5)这意味着你只要主课不要落下太多,奖学金随便拿(比赛获奖本身还有额外奖金)。
# 零基础学习 ACM 是否过于困难?
## 零基础学习 ACM 是否过于困难?
我并不这么觉得,原因如下
@@ -36,9 +36,11 @@ author:wenjing
③ 在初高中参加竞赛的学生的数量和质量有极可能已经有所下降,因为竞赛相关政策的紧缩,稀烂的强基计划替代了对竞赛友好的自主招生,选择全力投身竞赛,拼搏省队的学生有所下降,有基础的学生现在也不见得很强。
UPD at 2023/7/19从长期来看这个结论应该是没有错的但是很可惜如果您是2023届的新生您将遭遇紧缩政策下一波不得不来hdu的竞赛高材生截至笔者更新为止已经有五位NOI银牌选手和两位具备NOI银牌能力的选手提前加入了集训队也许对于零基础的同学而言仍然只要和别的零基础同学竞争保底的三个席位就好了。但从长远来看进队不是结束抢夺比赛机会才是开始。而且如果hdu能抢到这样的生源其他学校的水平大概率也会上涨就算有了比赛机会也很难说会不会拿铜遗憾结尾。如果您出于好奇想了解这荒谬的景象是如何诞生请参阅电子书[《整型溢出》](https://zhuanlan.zhihu.com/p/117660874)
进队的学生零基础偏少,如果你选择这条路你可能需要克服不小的困难
# 我应该以什么态度学习 ACM
## 我应该以什么态度学习 ACM
假如你是一位有信息竞赛基础,且得过省级奖项的前 oier您也没什么必要看这篇文章您已经完全熟悉了算法竞赛需要的一切我希望您不要有太大压力做最好的自己就行不要留下遗憾。对于零基础的同学也一样或许得奖后的绩点加成实在是过于诱人但竞赛获奖这种事情还是太难强求让自己压力太大得不偿失。
@@ -52,7 +54,7 @@ author:wenjing
之后的日子是灰暗的,浑浑噩噩的训练,知难而退放弃最好的高中的特长生名额。故事很长,我只是想说学竞赛不要太功利,竞赛终究是少数高手的游戏,做不到就是做不到,但这也仅仅只代表你的竞赛能力不够,你的人生并不是只有竞赛,大学也不只有 ACM 一条路(这很显然,不然我们社团应该改名为 ACM 社)
# 再谈 ACM 为我带来什么
## 再谈 ACM 为我带来什么
我初中成绩并不差,但发挥失常的话确实上不了我毕业的高中。我高考发挥失常,竞赛通过杭电三一成为保底。
@@ -64,7 +66,7 @@ author:wenjing
截止完成这篇文章为止,笔者仍在集训队中,我害怕自己被淘汰,不是因为我害怕自己失去参赛资格,而是我很难想象自己失去 ACM 的生活,我需要一个学习 ACM 的理由。给诸位讲个笑话,某一天我与朋友出门游玩,想不到话题,于是就开始讨论算法题的做法,从正午到日落。
# 算法思维与应试思维
## 算法思维与应试思维
众所周知ACM 是开卷竞赛,你可以携带纸质资料进入考场。
@@ -86,7 +88,7 @@ author:wenjing
也许在一次次陈旧腐朽的选拔性考试中,应试思维取得了压倒性的胜利。但在 ACM 中,算法思维依旧有一片净土。
# 数学与算法思维
## 数学与算法思维
那么,如何培养算法思维呢?我认为首先我们得学好数学。然而,我最总是在大一中听到这样的声音:“哎呀,烦死了,我们是学编程的,为什么要花那么多精力学数学,还占那么多学分,真讨厌。“然而,比起枯燥乏味的编程课,我最喜欢的还是数学课。数学在算法中无处不体现,可以说学好算法就是要学好数学,我现在复盘我初中 OI 生涯的失败,很大程度归因于数学基础的薄弱。以下为几个体现数学在算法中重要性的例子。
@@ -104,6 +106,6 @@ author:wenjing
优秀的数学思维能使你在理解算法的路上事半功倍,当然,算法的学习也能加深你对数学的理解。
# 结论
## 结论
大胆去学 ACM 吧,大一的空闲时间真的很多,去探索新事物,不试试怎么知道自己行不行。

View File

@@ -2,25 +2,25 @@
在之前的篇章中,我们向新手 acmer 推荐了两个编程网站——Luogu 与 Codeforces下面由笔者向各位介绍一下网站的详细用法。
# Luogu
## Luogu
进入 [https://www.luogu.com.cn/](https://www.luogu.com.cn/)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing1.png)
![](https://cdn.xyxsw.site/wenjing1.png)
## 社交模块
### 社交模块
做为一个刷题网站Luogu 提供了符合中文用户习惯的社交模块。体现于左侧边栏的讨论及主页的最近讨论,以及底部的“发射犇犇”系统。但是我并不建议 Acmer 使用该功能,因为 Luogu 主要面向初高中生甚至小学生等参加 NOIP 系列竞赛的用户,讨论不可避免存在一些低龄化现象。对于社交模块的使用,我推荐当且仅当一种做不出题的求助手段,这点放在之后题目模块讲解。
## 题目模块
### 题目模块
点开题库,我们看见以下界面
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing2.png)
![](https://cdn.xyxsw.site/wenjing2.png)
在上方我们可以筛选我们想要的题目,接下来我们点开 P1000 为例
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing3.png)
![](https://cdn.xyxsw.site/wenjing3.png)
右侧三个模块为折叠状态,下面介绍他们的作用
@@ -34,17 +34,17 @@
点击提交答案
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing4.png)
![](https://cdn.xyxsw.site/wenjing4.png)
左侧可以选择语言类型C++ 用户建议选择 C++14。
O2 优化是一种优化(废话)假如您的代码复杂度正确但 TLE可以尝试该选项。
## 记录模块
### 记录模块
怎么知道自己代码的问题出在哪里呢?记录模块是帮助你的好工具。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing5.png)
![](https://cdn.xyxsw.site/wenjing5.png)
AC通过该数据点
@@ -60,47 +60,47 @@ MLE空间超限 请检查是否递归爆栈、数组过大
OLE输出超限 放心你见不到的
## 题单模块
### 题单模块
点开侧栏题单
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing6.png)
![](https://cdn.xyxsw.site/wenjing6.png)
建议新手从官方精选题单开始,由浅入深,由简到难。等到对算法形成概念,针对漏洞补习时可以尝试用户分享题单(到那个阶段已经有很多手段去找题了,刘教练的题单就够你做了)
## 比赛模块
### 比赛模块
点开侧栏就能看见准备举办和已结束的比赛。笔者不建议大家在 Luogu 打比赛,首先赛制不一样,其次出题风格不一样,最后对于初学者 Luogu 比赛的难度曲线过大。
# Codeforces
## Codeforces
进入 [https://codeforces.com/?locale=en](https://codeforces.com/?locale=en)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing7.png)
![](https://cdn.xyxsw.site/wenjing7.png)
比起 Luogu这样的 UI 设计离 CN 互联网已经很远了然而比起更硬核的一些做题网站CF 的 UI 真是越看越顺眼)
右上角注册登录切语言(哇塞,可以选俄语,你说的对,但是 CF 是一款由俄罗斯开发的多人在线竞技游戏)
## HOME 模块
### HOME 模块
主页显示各种数据,主要为近期比赛的一些公告。
## TOP 模块
### TOP 模块
热帖如果擅长英语的话CF 的交流氛围还是不错的,做为一个答疑解惑的论坛肯定比国内强。
## CATALOG 模块
### CATALOG 模块
文档目录,你可以在这学习算法竞赛入门,体系化学习算法,只要你会英语
## CONTESTS
### CONTESTS
重中之重CF 的比赛系统可以说是我们选择这个网站的最大原因!
进入比赛页面
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing8.png)
![](https://cdn.xyxsw.site/wenjing8.png)
上方为将举办比赛显示开始时间UTC+8 也就是我们时区的时间)和持续时间大多都开始的比较晚,例如笔者就没有这么晚学习的习惯,所以一般赛后写题。比赛分为以下几种类型(例如写在括号里的 Div.2
@@ -112,22 +112,22 @@ Div.1、Div.2、Div.3、Div.4 数字越小难度越大。
下面以一场 Div.2 比赛为例,展示我们该如何打一场 CF。
## VP
### VP
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing9.png)
![](https://cdn.xyxsw.site/wenjing9.png)
这是一场笔者之前赛后补过的 Div.2,画面右下角分别为赛后公告和题解,右侧便是开启 VP 的按钮。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing10.png)
![](https://cdn.xyxsw.site/wenjing10.png)
<em>VP</em><em>模拟赛时的好处就是在虚拟参赛中获得真实比赛才能积累的经验,比如这里笔者发现通过前三题后,我应该先去看看 F 题因为做出来的人更多我有更大的可能性做出来ACM 中题目并不是 100% 按难度排序。</em>
*VP 模拟赛时的好处就是在虚拟参赛中获得真实比赛才能积累的经验,比如这里笔者发现通过前三题后,我应该先去看看 F 题因为做出来的人更多我有更大的可能性做出来ACM 中题目并不是 100% 按难度排序。*
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing11.png)
![](https://cdn.xyxsw.site/wenjing11.png)
进入 VP 后,我们可以发现比起正常赛后补题有了明显不同。
首先我们可以看见赛时某道题的通过人数,随比赛时间流逝 100% 仿真变化。而且也可以与当时的“虚拟选手”同步竞争,例如笔者这里就复制之前写过的代码荣登榜三(乐)
对于大多数比赛,采用 ICPC 赛制,解决某题得到的分数由该题当前的分数减去(不成功的提交次数)*50这里某道题的分数是由比赛开始时的分数随时间线性减少得到的。
对于大多数比赛,采用 ICPC 赛制,解决某题得到的分数由该题当前的分数减去 (不成功的提交次数)*50这里某道题的分数是由比赛开始时的分数随时间线性减少得到的。
也就是做题越快,错误次数越少,分数和排名就越高,这点大体是与 ACM 赛制相同的。
@@ -135,30 +135,30 @@ Div.1、Div.2、Div.3、Div.4 数字越小难度越大。
让我们点开 A 题,来看看如何提交答案
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing12.png)
![](https://cdn.xyxsw.site/wenjing12.png)
可以看见,右侧有一个 submit与 luogu 不同的是,你需要上传源代码文件(如 cpp然后选择 G++17 为语言,提交。
当然,你也可以点开上侧的 submit code
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing13.png)
![](https://cdn.xyxsw.site/wenjing13.png)
选择题目、语言,填写代码后提交,就和 Luogu 的方式一样了。
同样,在上侧 MY SUBMISSIONS 处可以查看已提交的代码和状态
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing14.png)
![](https://cdn.xyxsw.site/wenjing14.png)
## PROBLEMSET
### PROBLEMSET
同样CF 也有题库
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/wenjing15.png)
![](https://cdn.xyxsw.site/wenjing15.png)
如果你只想做某道题而不是某场比赛,这里也许更适合你。
不过 CF 的题库比较鸡肋,标签筛选也不是很方便(大概是把想要的标签在右上角分隔好)
# 总结
## 总结
笔者向读者详细介绍了两个 OJ至于如何让 OJ 更好的辅助你的 ACM 学习,我应该在什么时间节点或训练阶段,出于什么训练目的选择哪个网站,笔者留到下一个篇章继续介绍。

View File

@@ -58,7 +58,7 @@
打完比赛,建议钻研一下自己没做出的前一两题,写个题解。为什么要写题解呢,一个是方便以后来回顾,一个是加深印象,一个是把自己的思维用文字表达出来,这样能发现思维的漏洞(比如证明不严谨之类的)。题解写出来发不发博客就看个人喜好吧。作者以前也是坚持写博客写了很久。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/Axiomofchoice_1.png)
![](https://cdn.xyxsw.site/Axiomofchoice_1.png)
为什么要打 Codeforces 比赛呢?主要原因是打比赛有计时,有压力(怕掉分的压力),能让人提升更快。不要因为怕掉分就不参加了,你要相信只要你一直打比赛,你的 rating 曲线一定是波动上升的。

View File

@@ -1,6 +1,6 @@
# 3.2 算法杂谈
# 学计算机要先学算法吗?
## 学计算机要先学算法吗?
也许有的同学在高中阶段接触过信息学奥赛,那么也许你已经对基础的算法知识已经有了一定的了解。
@@ -10,19 +10,19 @@
学习算法的基础是拥有最基本的计算机素养,你需要优先学习一些基本的计算机概念、编程语言、简单的数据结构(数组、链表等),这些基本知识是你能够灵活利用算法的基础。
# 学了算法就相当于学好了计算机吗?
## 学了算法就相当于学好了计算机吗?
学好了算法当然不等于学好了计算机科学。计算机科学是一个非常庞大的知识体系,包括更为底层的计算机组成原理、编译原理等,更为表层的 AI开发等是一门综合性学科。总的来说算法是计算机科学中较为重要的一部分<strong>远远</strong>不是全部。
学好了算法当然不等于学好了计算机科学。计算机科学是一个非常庞大的知识体系,包括更为底层的计算机组成原理、编译原理等,更为表层的 AI开发等是一门综合性学科。总的来说算法是计算机科学中较为重要的一部分**远远**不是全部。
# 学算法就要用《算法导论》一类的书吗?
## 学算法就要用《算法导论》一类的书吗?
我的答案是否定的。它更适合作为“工具书”(就像你英语的词典那样),而不是一本适合新生入门学习的书。可以使用《我的第一本算法书》一类的更为基础更为有趣的算法内容。相比于完全严谨的逻辑推导, 初学者的诉求是在"看得见, 摸得着的例子和环境下探索和吸收新概念". 像这样的大部头可以在之后进行阅读.
我的答案是否定的。它更适合作为“工具书”(就像你英语的词典那样),而不是一本适合新生入门学习的书。可以使用《我的第一本算法书》一类的更为基础更为有趣的算法内容。相比于完全严谨的逻辑推导初学者的诉求是在"看得见摸得着的例子和环境下探索和吸收新概念". 像这样的大部头可以在之后进行阅读
# 学算法一定要用 C 语言吗?不用 C 语言可以吗?
## 学算法一定要用 C 语言吗?不用 C 语言可以吗?
不一定要用 C 语言。但是 C 语言作为一种贴近底层面向过程语言,对日后学习其他的语言会有较大的帮助。你也可以先学习 Python、JAVA 等等。学校的课程仅仅是教授一些比较基础的知识,如果想要真正掌握一门语言,需要在学校课程的基础上更进一大大大步。
# ACM 怎么说?
## ACM 怎么说?
前情提要,请尽量不要以功利的心态去参加 ACM你想要的与你能得到的可能存在过大落差
@@ -32,6 +32,6 @@ ACM 是美国计算机协会Association for Computing Machinery的缩写
在我校,参加 ACM 社团姑且叫做社团并不代表能够参加有含金量的团体赛ICPC、CCPC 等)。你需要先参加由我校教练刘春英老师组织的各种比赛,有资格进入集训队后,才有机会代表学校参加比赛(当然不限名额的个人赛想参加就参加)。
进入集训队后采取末位淘汰制度(最后留下来的人在 20 人左右),最后留下来的人才有机会参加比赛。<strong>因此个人并不推荐 0 基础的同学对于 ACM 过于执着</strong>,有 0 基础的同学最后进入校队的例子,不过这通常意味着你一天至少得刷一道算法题。如果还是想尝试的同学,可以去洛谷(www.luogu.com.cn)、Codeforces(www.codeforces.com)、Atcoder(atcoder.jp)等平台上注册账号,练习题目,参加这些网站定期组织的一些比赛。
进入集训队后采取末位淘汰制度(最后留下来的人在 20 人左右),最后留下来的人才有机会参加比赛。**因此个人并不推荐 0 基础的同学对于 ACM 过于执着**,有 0 基础的同学最后进入校队的例子,不过这通常意味着你一天至少得刷一道算法题。如果还是想尝试的同学,可以去洛谷 ([www.luogu.com.cn](http://www.luogu.com.cn))、Codeforces([www.codeforces.com](http://www.codeforces.com))、Atcoder([atcoder.jp](https://atcoder.jp/)) 等平台上注册账号,练习题目,参加这些网站定期组织的一些比赛。
如果经过一段时间的练习能够在 Codefoces[www.codeforces.com](http://www.codeforces.com))上达到 1400 以上的 Rating那么可以再观望观望参与 ACM。

View File

@@ -1,18 +1,18 @@
# 3.3 如何选择编程语言
# 编程语言的工具属性
## 编程语言的工具属性
在回答这个问题之前,需要各位同学明确的一点是,编程并不是一个独立的学科,像数学那样做题是学不好的。
编程语言的选择更像是锤子与扳手之间的选择,更大程度上看的是你需要解决什么样的问题。当你需要砸钉子的时候,使用螺丝刀总归是不顺手的,因此了解不同语言的特性,针对任务进行选择是非常有必要的。
# 编程语言特性
## 编程语言特性
首先附上一张经典老图
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnW0YQY58RXhwdtRj5k6ndlc.jpeg)
![](https://cdn.xyxsw.site/boxcnW0YQY58RXhwdtRj5k6ndlc.jpeg)
## C 语言/C++
### C 语言/C++
C 语言/C 艹一脉同源从图中来看C 和 C 艹都像多功能瑞士军刀说明其是用来做细活的工具C 上面的优盘说明其可以进行硬件开发的相关工作。
@@ -22,11 +22,11 @@ C 语言其实是一门优秀的承上启下的语言,既具有高级语言的
但是其功能毕竟受限,有时候用起来会苦恼其操作受限以及各种奇奇怪怪的 bug 问题。
<strong>如果为了增强自身的编程能力和计算机素养培养解决问题的能力C 语言的你的不二选择。在这里强烈推荐 jyy 老师的各类课程。(</strong><strong>[http://jyywiki.cn/](http://jyywiki.cn/)</strong><strong></strong>
**如果为了增强自身的编程能力和计算机素养培养解决问题的能力C 语言的你的不二选择。在这里强烈推荐 jyy 老师的各类课程。([http://jyywiki.cn/](http://jyywiki.cn/)**
<strong>我们的任务一部分会使用 C 语言,一方面培养大家编程能力,一方面辅助大家期末考试。</strong>
**我们的任务一部分会使用 C 语言,一方面培养大家编程能力,一方面辅助大家期末考试。**
## C++
### C++
现代 C++ 程序可看成以下三部分组成。
@@ -34,7 +34,7 @@ C 语言其实是一门优秀的承上启下的语言,既具有高级语言的
- 更高级的语言特征,可自定义数据类型
- 标准库
<strong>C++ 既有 C 面向过程的特点,又拥有面向对象的特性,是一门系统级的语言。</strong>
**C++ 既有 C 面向过程的特点,又拥有面向对象的特性,是一门系统级的语言。**
编译器、操作系统的开发,高性能服务器的开发,游戏引擎的开发,硬件编程,深度学习框架的开发......只要是和底层系统或者是与性能相关的事情,通常都会有 C++ 的一席之地。
@@ -46,7 +46,7 @@ Python 在图里是电锯,适合干比较“狂野”的任务,也是深度
使用缩进控制语句是此语言的特点。
<strong>作为深度学习的主要使用语言,我们将以</strong><strong>P</strong><strong>ython 为主。</strong>
**作为深度学习的主要使用语言,我们将以****P****ython 为主。**
## JAVA
@@ -54,8 +54,8 @@ Python 在图里是电锯,适合干比较“狂野”的任务,也是深度
他太老了,虽然不少框架都依托于 Java但是不得不说一些地方略有落后。
<strong>频繁应用于</strong><strong>W</strong><strong>eb 开发,安卓应用等等。</strong>
**频繁应用于****W****eb 开发,安卓应用等等。**
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnPv2FcyQxGLjYHThSaJNwRf.jpeg)
![](https://cdn.xyxsw.site/boxcnPv2FcyQxGLjYHThSaJNwRf.jpeg)
当然还有各种形形色色的编程语言等着同学们去探索。

View File

@@ -1,39 +1,39 @@
# FAQ常见问题
# 我完全没基础觉得好难呜呜
## 我完全没基础觉得好难呜呜
教育除了知识的记忆之外, 更本质的是能力的训练, 即所谓的 training. 而但凡 training 就必须克服一定的难度, 否则你就是在做重复劳动, 能力也不会有改变. 如果遇到难度就选择退缩, 或者让别人来替你克服本该由你自己克服的难度, 等于是自动放弃了获得 training 的机会
教育除了知识的记忆之外更本质的是能力的训练即所谓的 training. 而但凡 training 就必须克服一定的难度否则你就是在做重复劳动能力也不会有改变如果遇到难度就选择退缩或者让别人来替你克服本该由你自己克服的难度等于是自动放弃了获得 training 的机会
# 我觉得无从下手
## 我觉得无从下手
尝试借鉴他人的代码也未尝不可,但是要保证每一行都看懂哦
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnQ4rvJqVbXJaWMOwceHdrQb.png)
![](https://cdn.xyxsw.site/boxcnQ4rvJqVbXJaWMOwceHdrQb.png)
# 我感觉讲义写的不够细
## 我感觉讲义写的不够细
首先,我无法照顾到每一个人的情况,保证你每一个地方都看懂
其次,很多地方的坑是故意留给你让你尝试独立解决问题的。
# 我觉得我以后不会从事 C 相关的工作
## 我觉得我以后不会从事 C 相关的工作
这种"只要不影响我现在 survive, 就不要紧"的想法其实非常的利己和短视: 你在专业上的技不如人, 迟早有一天会找上来, 会影响到你个人职业生涯的长远的发展
这种"只要不影响我现在 survive, 就不要紧"的想法其实非常的利己和短视你在专业上的技不如人迟早有一天会找上来会影响到你个人职业生涯的长远的发展
更严重的是,他可能会透支学校的信誉。
<strong>同时,先学好 C 语言对你有以下帮助:</strong>
**同时,先学好 C 语言对你有以下帮助:**
1. 掌握计算机底层知识C 语言是一种高效的系统级语言,它的语法和数据结构设计直接映射到底层计算机硬件,通过学习 C 语言可以更深入地了解计算机底层运作原理,为理解更高级的编程语言和开发工具奠定基础。
2. 提高编程能力C 语言的语法相对较为简单,但是它要求程序员手动管理内存,这需要编程者深入了解内存结构和指针的使用。通过学习 C 语言,可以锻炼编程能力,提高代码质量和效率。
3. 能够理解其他语言C 语言是很多编程语言的基础,如 C++、Java、Python 等语言都从 C 语言继承了很多特性。因此,学好 C 语言可以帮助你更好地理解其他编程语言的设计思路和工作原理。
4. 开发底层软件:由于 C 语言具有高效、灵活、可移植等特点,因此它被广泛用于开发操作系统、嵌入式系统、网络协议、游戏引擎等底层软件。学习好 C 语言可以为你将来从事底层软件开发提供必要的基础知识。
# 我感觉我写了也不会学到啥
## 我感觉我写了也不会学到啥
复杂的问题总是存在简单的解释C 语言虽然不擅长带 GUI 界面的编写,但是我们每日在用的都和他息息相关,那些庞大的系统也无非就是由这些简单的东西搭建而成的
# 我觉得我没有学懂 C 语言就开始别的合适吗
## 我觉得我没有学懂 C 语言就开始别的合适吗
学习本章内容更大程度上是为了让你搞清楚编程世界运行的基本原理
@@ -45,19 +45,19 @@ NJU-ICS-PA 南京大学计算机系统基础
但是建议大家大二再进行尝试,非常难
# 我总觉得文章没写清楚
## 我总觉得文章没写清楚
你毕业后进入公司/课题组, 不会再有讲义具体地告诉你应该做什么, 总有一天你需要在脱离讲义的情况下完成任务. 我们希望你现在就放弃"讲义和框架代码会把我应该做的一切细节清楚地告诉我"的幻想, 为自己的成长负起责任:
你毕业后进入公司/课题组不会再有讲义具体地告诉你应该做什么总有一天你需要在脱离讲义的情况下完成任务我们希望你现在就放弃"讲义和框架代码会把我应该做的一切细节清楚地告诉我"的幻想为自己的成长负起责任
- 不知道在说什么, 说明你对知识点的理解还不够清楚, 这时候你应该去看书/看手册
- 不知道要做什么/怎么做, 说明你的系统观好是零碎的, 理解不了系统中各个模块之间的联系, 这时候你应该 RTFSC, 尽自己最大努力梳理并理解系统中的一切细节
- bug 调不出来, 说明你不清楚程序正确的预期行为, 你需要 RTFSC 理解程序应该如何运行; 此外也说明你不重视工具和方法的使用, 你需要花时间去体验和总结它们
- 不知道在说什么说明你对知识点的理解还不够清楚这时候你应该去看书/看手册
- 不知道要做什么/怎么做说明你的系统观好是零碎的理解不了系统中各个模块之间的联系这时候你应该 RTFSC, 尽自己最大努力梳理并理解系统中的一切细节
- bug 调不出来说明你不清楚程序正确的预期行为你需要 RTFSC 理解程序应该如何运行; 此外也说明你不重视工具和方法的使用你需要花时间去体验和总结它们
如果你发现自己有以上情况, 你还是少抱怨, 多吃苦吧.
如果你发现自己有以上情况你还是少抱怨多吃苦吧
当然,如果你发现有更好的想法欢迎联系我
# 这些对我太简单了
## 这些对我太简单了
你可以从广度和深度两个角度对自己进行拔高
@@ -65,8 +65,8 @@ NJU-ICS-PA 南京大学计算机系统基础
有且仅有大学有这样好的资源帮助你了
# <strong>坚持了好久还是搞不定, 我想放弃了</strong>
## **坚持了好久还是搞不定我想放弃了**
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnuNXrb5zOppCZAlGQ19wuDk.jpg)
![](https://cdn.xyxsw.site/boxcnuNXrb5zOppCZAlGQ19wuDk.jpg)
也许是你坚持的姿势不对,来和 ZZM 聊聊吧

View File

@@ -2,29 +2,31 @@
初学 C 语言,第一个问题莫过于用什么软件编写 C 语言程序。学校的老师可能会推荐包括但不限于 VC6.0CodeBlocksdevC++Visual Studio2013 等,如果你的电脑不是老年机,那么以上软件衷心建议你不要去使用,过于老旧了。
# Windows-Visual Studio
## Windows-Visual Studio
[vs2022(Visual Studio 2022)指南&&技巧要领](https://www.bilibili.com/video/BV1Xt411g7jT?vd_source=699341ff80cb01917fb43665199a48dd)
[vs2022(Visual Studio 2022) 指南&&技巧要领](https://www.bilibili.com/video/BV1Xt411g7jT)
Visual Studio (以下简称 VS )是 Windows 下最完美的 C/C++ 等语言的开发平台,有“宇宙第一 IDE”之称功能丰富开箱即用。目前更新到 2022 版。
<Bilibili bvid='BV1Xt411g7jT'/>
Visual Studio以下简称 VS是 Windows 下最完美的 C/C++ 等语言的开发平台,有“宇宙第一 IDE”之称功能丰富开箱即用。目前更新到 2022 版。
什么是 IDE什么是代码编辑器什么是编译器等等细碎问题参考文档 [3.1 该使用哪个编辑器???](3.1%E8%AF%A5%E4%BD%BF%E7%94%A8%E5%93%AA%E4%B8%AA%E7%BC%96%E8%BE%91%E5%99%A8%EF%BC%9F%EF%BC%9F%EF%BC%9F.md) 看不懂的话直接无脑装
## <strong>下载</strong>
### **下载**
[https://visualstudio.microsoft.com/zh-hans/downloads/](https://visualstudio.microsoft.com/zh-hans/downloads/)
选择社区版
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnhNeAnlrbcdJciMUY9oNTuc.png)
![](https://cdn.xyxsw.site/boxcnhNeAnlrbcdJciMUY9oNTuc.png)
社区版和专业版等的区别:社区版免费,功能上几乎无差别
## 安装
### VS 安装
选择 C++ 桌面开发其他不用选有需要了再说。另外Python 开发不好使,不要像我一样选 Python 开发。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnkjmKcCxIgRIzA5kyUZckye.png)
![](https://cdn.xyxsw.site/boxcnkjmKcCxIgRIzA5kyUZckye.png)
安装完成后,一般来说 VS 不会自动创建桌面快捷方式,你需要到开始菜单中启动 VS。
@@ -32,25 +34,25 @@ Visual Studio (以下简称 VS )是 Windows 下最完美的 C/C++ 等语言
首次打开应该会让你选择开发环境和主题,建议开发环境选择 C++ ,主题根据个人喜好选择。
## 创建项目
### 创建项目
VS 是项目制,你需要创建一个项目才能开始编写代码并运行。
打开 VS会打开如下界面我使用深色主题在此处单击“创建新项目”
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn6MgNnY2qBd1yAudeirx6Sh.png)
![](https://cdn.xyxsw.site/boxcn6MgNnY2qBd1yAudeirx6Sh.png)
在创建新项目页面中选择项目模板为控制台应用(空项目亦可,后续手动添加.c 源文件),并单击下一步
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnFwZpWZ3fQkdd3mCO8Mr9Wj.png)
![](https://cdn.xyxsw.site/boxcnFwZpWZ3fQkdd3mCO8Mr9Wj.png)
为你的项目起一个名字以及选择项目的位置一般默认即可如果你有强迫症C 盘一定不能放个人数据,请自行修改。完成后单击“创建”
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnkxd472wIT39DbEiBsyPWzf.png)
![](https://cdn.xyxsw.site/boxcnkxd472wIT39DbEiBsyPWzf.png)
自此就创建了一个项目了,你将会到达如下界面:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnvOGdjKLnvXvJM7nlE8yVcb.png)
![](https://cdn.xyxsw.site/boxcnvOGdjKLnvXvJM7nlE8yVcb.png)
其中,左侧(如果在一开始没有选择 C++ 开发环境的话可能在右侧)为资源管理器,列出了本项目所用到的所有文件,包括代码(外部依赖项、源文件、头文件),以及将来开发图形化界面所需的资源文件;最中间占据面积最多的是代码编辑器窗口,你以后将会在这里编写你的 C 语言代码。最下面是输出窗口,源代码进行编译时,会在此处给出编译进度以及可能的代码中的错误。
@@ -58,91 +60,94 @@ VS 是项目制,你需要创建一个项目才能开始编写代码并运行
阅读完以后,就可以将代码全部删去,编写自己的代码了。
注意控制台项目初始源文件后缀为.cpp 为 C++ 文件,如果编写 C 语言<strong>建议将后缀改为.c</strong>。.cpp 存在隐患:如果不小心使用了 C++ 的语法而非 C 存在的语法,编译器并不会报错,且 C 与 C++ 在某些特性存在区别。
注意控制台项目初始源文件后缀为.cpp 为 C++ 文件,如果编写 C 语言**建议将后缀改为.c**。.cpp 存在隐患:如果不小心使用了 C++ 的语法而非 C 存在的语法,编译器并不会报错,且 C 与 C++ 在某些特性存在区别。
## “运行”你的 C 语言代码
### “运行”你的 C 语言代码
C 语言是编译型语言,因此说“运行”代码其实并不是十分合适,不过我们初学,不用过分抠字眼,知道什么意思即可。
当你编写完自己的代码后,即可单击“本地 Windows 调试器”(或者使用快捷键 F5进行“运行”。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnhTxhUYMHeYHdrq0zWzLomb.png)
![](https://cdn.xyxsw.site/boxcnhTxhUYMHeYHdrq0zWzLomb.png)
你可能会发现在“本地 Windows 调试器”右侧还有一个绿色三角形,并且单击这个也可以“运行”,这两个的区别在于“本地 Windows 调试器”是调试运行,右侧那个是不调试直接运行。
## scanf 报错
### scanf 报错
如果你的代码被 VS 提示“This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.”
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnfrxYjk5CCjMfY0mLK1B1Ze.png)
![](https://cdn.xyxsw.site/boxcnfrxYjk5CCjMfY0mLK1B1Ze.png)
需要你在项目-xxx 属性xxx 是你的项目名)-C/C++-代码生成-安全检查里将安全检查禁用
需要你在项目-xxx 属性xxx 是你的项目名)-C/C++-代码生成 - 安全检查里将安全检查禁用
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcniHhCIUQY0oB3ALlxqgciLd.png)
![](https://cdn.xyxsw.site/boxcniHhCIUQY0oB3ALlxqgciLd.png)
## 调试
### 调试
IDE 相比于代码编辑器,最强大的一点莫过于成熟的调试系统。通过调试,可以快速定位代码中没有被编译器检查出来的逻辑错误。如果需要调试,则可以在这个位置单击,打下断点,并且运行程序,程序运行时,就会在此处暂停下来,暂停时就可以查看各个变量的值了。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnydHyaNPqUEVVWmbdGofX0d.png)
![](https://cdn.xyxsw.site/boxcnydHyaNPqUEVVWmbdGofX0d.png)
## <strong>深色主题</strong>
### **深色主题**
需要深色主题请在工具-主题里更改为深色
需要深色主题请在工具 - 主题里更改为深色
## Tips
### Tips
### 仔细查看报错
#### 仔细查看报错
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnC6TAAdtS0P5HzebFgFn2lc.png)
![](https://cdn.xyxsw.site/boxcnC6TAAdtS0P5HzebFgFn2lc.png)
如果程序代码中出现红色波浪线,则表示该处代码有“错误”,并且该处的错误会同步显示在下面的这个位置,单击即可看到错误详情。如果代码中出现绿色波浪线,则表示该处代码中有警告。警告和错误的区别是警告可以通过编译运行,但编译器认为你这里可能写错了;错误是完全不可以通过编译。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn7zL0QFakVTpYBdpOmmWOvc.png)
![](https://cdn.xyxsw.site/boxcn7zL0QFakVTpYBdpOmmWOvc.png)
### 善用提示
#### 善用提示
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn2ouk043lNQEUkVkIS7bSSd.png)
![](https://cdn.xyxsw.site/boxcn2ouk043lNQEUkVkIS7bSSd.png)
当你打一些函数名或者关键字时VS 会给出你语法提示,如果这个提示正确,按下 Tab 键即可将这个提示补全到你的代码里;或者你也可以跟着这个提示打一遍,防止打错关键字。
## VS 的缺点
### VS 的缺点
过于庞大,很多功能对于初学者来说用不上,对电脑的性能也有略微的要求,但瑕不掩瑜,他的开箱即用的使用体验还是很不错的。
# Windows-Visual Studio Code
## Windows-Visual Studio Code
Visual Studio Code以下简称 vscode 和 Visual Studio 都是微软开发的软件,区别在于 Visual Studio Code 是一个比较轻量的代码编辑器,在没有经过配置的情况下一般只能编写和查看代码,而不能运行,并且 Visual Studio Code 跨平台,在安装了丰富的插件后体验不输于一众 IDE。
Visual Studio Code以下简称 vscode和 Visual Studio 都是微软开发的软件,区别在于 Visual Studio Code 是一个比较轻量的代码编辑器,在没有经过配置的情况下一般只能编写和查看代码,而不能运行,并且 Visual Studio Code 跨平台,在安装了丰富的插件后体验不输于一众 IDE。
## 安装
> NX 的留言:
> 鄙人认为 C 的初学者应该使用 VSCode 更佳,环境准备可见鄙人博客 [『C/C++』VScode 环境配置](https://nickxu.me/2021/12/31/cc-vscode-huan-jing-pei-zhi/)
### 安装软件本体
### vscode 安装
#### 安装软件本体
[https://code.visualstudio.com/](https://code.visualstudio.com/)
在该网站进行下载,并安装,安装完成并打开后可以根据右下角的提示来修改显示语言等
### 安装编译器
#### 安装编译器
如果你电脑上下载有 VS那么安装编译器这一环节可以省略。如果电脑上没有 VS则需要安装 VS或者下载其他 C 语言编译器,如 gccclangicc 等
## 创建“项目”
### 创建“项目”
vscode 的项目和 VS 不同vscode 的项目比较松散,并没有 VS 那样是一套非常完善的项目系统。
首先需要一个空文件夹,并在 vscode 里打开这个文件夹。然后点击文件-新建文本文件,并选择语言为 C 语言。此时如果你是第一次创建 C 语言文件,那么右下角会弹出提示,提示你安装 C/C++ 插件,安装即可。
首先需要一个空文件夹,并在 vscode 里打开这个文件夹。然后点击文件 - 新建文本文件,并选择语言为 C 语言。此时如果你是第一次创建 C 语言文件,那么右下角会弹出提示,提示你安装 C/C++ 插件,安装即可。
## 编写代码并运行
### 编写代码并运行
编写完代码后,保存文件,并点击运行-启动调试
编写完代码后,保存文件,并点击运行 - 启动调试
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnim98FJybpkGl8sfqxP9v9b.png)
![](https://cdn.xyxsw.site/boxcnim98FJybpkGl8sfqxP9v9b.png)
此时会弹出如下选择框,我的电脑上同时安装有 VS 和 gcc 编译器因此有两个大部分的电脑上应该只有一个“C++ (Windows)”,选择你电脑上的编译器并运行即可。
至此就已经完成了编程和调试的基本功能。如果你想要更丰富的功能比如多文件编译等等可以自行去网上搜索相关的配置教程。vscode 配置好了是非常好用的,但缺点就在于配置比较麻烦。
# Windows-CLion
## Windows-CLion
CLion 是 jetbrains 家族的 C 语言 IDE
@@ -150,38 +155,41 @@ CLion 是 jetbrains 家族的 C 语言 IDE
收费软件,但可以从 GitHub 学生包里白嫖,喜欢折腾或者喜欢 jetbrains 家族软件风格的可以自己去折腾折腾。
# Mac OS-Visual Studio Code
## Mac OS-Visual Studio Code
用法和 Windows 的差不多,但由于 Mac OS 自带 clang 编译器,所以无需额外安装编译器。
# Mac OS-CLion
> NX 的留言:
> 使用自带的 clang 的确没问题,但是如果你想在 macOS 上使用 gcc/g++ [可参考鄙人的博客 在 Mac 的 VSC 中使用 g++ 编译器](https://nickxu.me/2023/04/04/%E5%9C%A8Mac%E7%9A%84VSCode%E4%B8%AD%E4%BD%BF%E7%94%A8g-%E7%BC%96%E8%AF%91%E5%99%A8)
## Mac OS-CLion
同样和 Windows 的差不多。
# Mac OS-Xcode
## Mac OS-Xcode
XCode 是 mac 官方的 IDE能编写所有 mac 家族设备的软件。但缺点是没有中文。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn05Ca6Wu5TxFMplZCw2N8Jb.png)
![](https://cdn.xyxsw.site/boxcn05Ca6Wu5TxFMplZCw2N8Jb.png)
打开以后选择 Create a new Xcode project选择 macOS-Command Line Tool
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnbnrVCmNGfriHhU5pL76gsd.png)
![](https://cdn.xyxsw.site/boxcnbnrVCmNGfriHhU5pL76gsd.png)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnnjaObP5JzpICUx1PMO9MQg.png)
![](https://cdn.xyxsw.site/boxcnnjaObP5JzpICUx1PMO9MQg.png)
两个空里第一个填项目名,第二个随便填就行
next 后选择项目保存的位置,之后即可到达以下界面:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnl06p0ZS8SSQsWJNLQLYIjc.png)
![](https://cdn.xyxsw.site/boxcnl06p0ZS8SSQsWJNLQLYIjc.png)
点左上方小三角即可运行
在行号上点击并运行即可调试
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnmRygjmZfwFzODP2N6bVoEh.png)
![](https://cdn.xyxsw.site/boxcnmRygjmZfwFzODP2N6bVoEh.png)
# Linux
## Linux
## 你都用 Linux 了你还来问我?一边玩去
### 你都用 Linux 了你还来问我?一边玩去

View File

@@ -3,7 +3,7 @@
- 本篇不需要任何前置知识,推荐在学习 C 语言和学完 C 语言后各看一遍。
- 我们鼓励你在解决问题的时候进行思考,锻炼解决问题的能力,而不只是成为一个做代码翻译工作的“码农”。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/YAOvb6gquofiAYxsn3tcxcCYngf.png)
![](https://cdn.xyxsw.site/YAOvb6gquofiAYxsn3tcxcCYngf.png)
解决编程问题的常见误区:
@@ -13,11 +13,11 @@
如果你计划得足够好并且代码编写得正确,你的代码将在第一次工作。即便它第一次不起作用,那么你至少有一个对于代码如何调试的可靠计划。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/HMipbO4vSoM3jhxSZ7Kcuddqnxh.png)
![](https://cdn.xyxsw.site/HMipbO4vSoM3jhxSZ7Kcuddqnxh.png)
## Work an Example Yourself
尝试设计算法的第一步是<strong>自己(手动)处理至少一个问题实例,为每个参数选择特定值。</strong>往往需要确定<strong>一个正确的示例,以及错误的示例。</strong>
尝试设计算法的第一步是**自己(手动)处理至少一个问题实例,为每个参数选择特定值。**往往需要确定**一个正确的示例,以及错误的示例。**
如果你在这一步陷入困境,这通常意味着两件事中的一件。第一种情况是问题不明确,不清楚你应该做什么。在这种情况下,你必须在继续之前解决问题。如果你正在解决自己创造的问题,你可能需要更仔细地思考正确的答案应该是什么,并完善你对问题的定义。
@@ -25,15 +25,15 @@
## Write Down What You Just Did
这一步中,必须思考解决问题所做的工作,并写下<strong>解决该特定实例的步骤。</strong>思考这一步骤的另一种方式是,写下一组清晰的指示,<strong>其他人可以按照这些指示来重现刚刚解决的特定问题实例的答案</strong>。如果在步骤 1 中执行了多个实例,那么也将重复步骤 2 多次,对步骤 1 中的每个实例重复一次。如果一条指令有点复杂,那没关系,只要指令稍后有明确的含义,我们将把这些复杂的步骤转化为它们自己的编程问题,这些问题将单独解决。
这一步中,必须思考解决问题所做的工作,并写下**解决该特定实例的步骤。**思考这一步骤的另一种方式是,写下一组清晰的指示,**其他人可以按照这些指示来重现刚刚解决的特定问题实例的答案**。如果在步骤 1 中执行了多个实例,那么也将重复步骤 2 多次,对步骤 1 中的每个实例重复一次。如果一条指令有点复杂,那没关系,只要指令稍后有明确的含义,我们将把这些复杂的步骤转化为它们自己的编程问题,这些问题将单独解决。
## Generalize Your Steps
<strong>将步骤 2 得到的具体步骤,抽象为一般性的结论。</strong>有时可能很难概括步骤。发生这种情况时,返回步骤 1 和 2 可能会有所帮助。做更多的问题实例将提供更多的信息供参考,更能帮助深入算法。这个过程通常被称为编写“伪代码”,以编程方式设计算法,而不使用特定的目标语言。几乎所有的程序员在编写任何实际代码之前都会使用这种方法来确保他们的算法是正确的。
**将步骤 2 得到的具体步骤,抽象为一般性的结论。**有时可能很难概括步骤。发生这种情况时,返回步骤 1 和 2 可能会有所帮助。做更多的问题实例将提供更多的信息供参考,更能帮助深入算法。这个过程通常被称为编写“伪代码”,以编程方式设计算法,而不使用特定的目标语言。几乎所有的程序员在编写任何实际代码之前都会使用这种方法来确保他们的算法是正确的。
## Test Your Algorithm
在步骤 3 之后,我们有了一个我们认为正确的算法。然而,我们完全有可能在这一路上搞砸了。步骤 4 的主要目的是确保我们的步骤在继续之前是正确的。为了实现这一点,我们使用<strong>不同于设计算法时使用的参数值</strong>来测试我们的算法。我们手动执行算法,并将其获得的答案与正确的答案进行比较。如果它们不同,那么我们知道我们的算法是错误的。我们使用的测试用例(参数值)越多,我们就越能确信我们的算法是正确的。不幸的是,通过测试无法确保我们的算法是正确的。要完全确定你的算法是正确的,唯一的方法就是正式证明它的正确性(使用数学证明),这超出了这个专门化的范围。
在步骤 3 之后,我们有了一个我们认为正确的算法。然而,我们完全有可能在这一路上搞砸了。步骤 4 的主要目的是确保我们的步骤在继续之前是正确的。为了实现这一点,我们使用**不同于设计算法时使用的参数值**来测试我们的算法。我们手动执行算法,并将其获得的答案与正确的答案进行比较。如果它们不同,那么我们知道我们的算法是错误的。我们使用的测试用例(参数值)越多,我们就越能确信我们的算法是正确的。不幸的是,通过测试无法确保我们的算法是正确的。要完全确定你的算法是正确的,唯一的方法就是正式证明它的正确性(使用数学证明),这超出了这个专门化的范围。
确定好的测试用例是一项重要的技能,可以随着实践而提高。对于步骤 4 中的测试,您需要使用至少产生几个不同答案的情况进行测试(例如,如果您的算法有“是”或“否”答案,则应使用同时产生“是”和“否”的参数进行测试)。您还应该测试任何角落情况,其中行为可能与更一般的情况不同。每当您有条件决定(包括计算位置的限制)时,您应该在这些条件的边界附近测试潜在的角点情况。
@@ -47,7 +47,7 @@
在黑盒测试中,测试人员只考虑功能的预期行为,而不考虑设计测试用例的任何实现细节。缺乏对实现细节的访问是这种测试方法的由来——函数的实现被视为测试人员无法查看的“黑盒子”。
事实上我们无需执行步骤 1-5 就能够为假设问题设想好的测试用例。实际上,在开始解决问题之前,您可以针对问题提出一组黑盒测试。一些程序员提倡<strong>测试优先</strong>的开发方法。一个优点是,如果您在开始之前编写了一个全面的测试套件,那么在实现代码之后就不太可能在测试上有所疏漏。另一个优点是,通过提前考虑你的情况,你在开发和实现算法时能够降低错误率。
事实上我们无需执行步骤 1-5 就能够为假设问题设想好的测试用例。实际上,在开始解决问题之前,您可以针对问题提出一组黑盒测试。一些程序员提倡**测试优先**的开发方法。一个优点是,如果您在开始之前编写了一个全面的测试套件,那么在实现代码之后就不太可能在测试上有所疏漏。另一个优点是,通过提前考虑你的情况,你在开发和实现算法时能够降低错误率。
- 选择测试用例的一些建议
@@ -65,4 +65,3 @@
## Debug Program
一旦在代码中发现了问题,就需要修复它,这个过程称为调试。许多新手程序员(甚至一些经验丰富的程序员)以临时方式调试,试图更改代码中的某些内容,并希望它能解决他们的问题。这样的方法很少有效,常常会导致很多挫折。

View File

@@ -1,10 +1,12 @@
# C 语言前置概念学习
如何学习 C 语言?<strong>第一步:Throw away the textbook。</strong>也许你可以通过以下途径:
如何学习 C 语言?**第一步:Throw away the textbook。**也许你可以通过以下途径:
以下方式难度由易到难,但并不意味着收获由小到大:
1.Video[B 站翁恺的 C 语言课程](https://www.bilibili.com/video/BV19W411B7w1?spm_id_from=333.337.search-card.all.click&vd_source=da5a5affb1b0c71c0d7e410b1d1a3c17)(非常基础,缺点是只看视频学的过浅)
1.Video[B 站翁恺的 C 语言课程](https://www.bilibili.com/video/BV1dr4y1n7vA)(非常基础,缺点是只看视频学的过浅)
<Bilibili bvid='BV1dr4y1n7vA'/>
2.MOOC[翁凯 C 课程的 MOOC 慕课](https://www.icourse163.org/course/ZJU-9001)(同上,慕课的习题和 Projects 性价比不高,几乎没有差别)
@@ -12,13 +14,17 @@
4.Web[CNote](https://github.com/coderit666/CNote)(例子密集,学习曲线平滑,覆盖面广且具有深度)
5.Book<strong>教材替换用书——《C Primer Plus》</strong>(基础且深入的恰到好处,有一定拓展,可能后面的章节有点难懂,是一本不可多得的好书,不要忽视课本习题及 Projects
::: tip 📥
《C Primer Plus》第六版中文版216MB附件下载 <Download url="https://cdn.xyxsw.site/files/C%20Primer%20Plus%E7%AC%AC6%E7%89%88%20%E4%B8%AD%E6%96%87%E7%89%88.pdf"/>
:::
6.MOOC[Introductory C Programming 专项课程](https://www.coursera.org/specializations/c-programming)<strong>全英文</strong>,好处是涉及到计算机思维,包含许多常用 tools 的教学例如 git、make、emacs、gdb视频讲解结合文档阅读对于 C 的重要核心知识讲解透彻,难度颇高,建议用作提升
5.Book**教材替换用书——《C Primer Plus》**(基础且深入的恰到好处,有一定拓展,可能后面的章节有点难懂,是一本不可多得的好书,不要忽视课本习题及 Projects
6.MOOC[Introductory C Programming 专项课程](https://www.coursera.org/specializations/c-programming)**全英文**,好处是涉及到计算机思维,包含许多常用 tools 的教学例如 git、make、emacs、gdb视频讲解结合文档阅读对于 C 的重要核心知识讲解透彻,难度颇高,建议用作提升)
7.Web[LinuxC 一站式编程](https://akaedu.github.io/book/)(难度大,枯燥硬核,收获多,基于 linux
### 学习建议:可以选择其一或多种学习
## 学习建议:可以选择其一或多种学习
- 对于缺乏计算机基础这里的基础指的是计算机的日常使用的同学1、2是不错的选择但在学完后要选择 4、5、6 进行补充巩固提高。
- 对于有一定计算机基础的同学,直接上手 4、5、6 都是很不错的选择。
@@ -34,6 +40,6 @@
计算机思维与计算机科学与编码能力
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/Hqzbbs6iYobnxWxz11Ocfa9gnHd.png)
![](https://cdn.xyxsw.site/Hqzbbs6iYobnxWxz11Ocfa9gnHd.png)
### <strong>CS education is more than just “learning how to code”!</strong>
### **CS education is more than just “learning how to code”!**

View File

@@ -6,13 +6,13 @@
使用链表存储数据,不强制要求数据在内存中集中存储,各个元素可以分散存储在内存中。例如,使用链表存储 {1,2,3},各个元素在内存中的存储状态可能是:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnuwZzqX4dF8xKTYajwrDSxf.png)
![](https://cdn.xyxsw.site/boxcnuwZzqX4dF8xKTYajwrDSxf.png)
可以看到,数据不仅没有集中存放,在内存中的存储次序也是混乱的。那么,链表是如何存储数据间逻辑关系的呢?
链表存储数据间逻辑关系的实现方案是:为每一个元素配置一个指针,每个元素的指针都指向自己的直接后继元素,如下图所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnAnkVAJmMT0NSNvo6crXYAd.png)
![](https://cdn.xyxsw.site/boxcnAnkVAJmMT0NSNvo6crXYAd.png)
显然,我们只需要记住元素 1 的存储位置,通过它的指针就可以找到元素 2通过元素 2 的指针就可以找到元素 3以此类推各个元素的先后次序一目了然。像图 2 这样,数据元素随机存储在内存中,通过指针维系数据之间“一对一”的逻辑关系,这样的存储结构就是链表。
@@ -20,13 +20,13 @@
在链表中,每个数据元素都配有一个指针,这意味着,链表上的每个“元素”都长下图这个样子:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcncRc5OKZROtxC9rpQYxrjvf.png)
![](https://cdn.xyxsw.site/boxcncRc5OKZROtxC9rpQYxrjvf.png)
数据域用来存储元素的值,指针域用来存放指针。数据结构中,通常将这样的整体称为结点。
也就是说,链表中实际存放的是一个一个的结点,数据元素存放在各个结点的数据域中。举个简单的例子,图 3 中 {1,2,3} 的存储状态用链表表示,如下图所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn0VMYQlez7tQTNkTPDkCsvg.png)
![](https://cdn.xyxsw.site/boxcn0VMYQlez7tQTNkTPDkCsvg.png)
在 C 语言中,可以用结构体表示链表中的结点,例如:
@@ -42,21 +42,21 @@ typedef struct Node* Link;
图 4 所示的链表并不完整,一个完整的链表应该由以下几部分构成:
头指针:是指向链表中一个结点所在存储位置的指针。如果链表中有头结点,则头指针指向头结点;若链表中没有头结点,则头指针指向链表中第一个数据结点(也叫首元结点)。
头指针是指向链表中一个结点所在存储位置的指针。如果链表中有头结点,则头指针指向头结点;若链表中没有头结点,则头指针指向链表中第一个数据结点(也叫首元结点)。
链表有头指针,当我们需要使用链表中的数据时,我们可以使用遍历查找等方法,从头指针指向的结点开始,依次搜索,直到找到需要的数据;反之,若没有头指针,则链表中的数据根本无法使用,也就失去了存储数据的意义。
结点:链表中的节点又细分为头结点、首元结点和其它结点:
头结点:位于链表的表头,即链表中第一个结点,其一般不存储任何数据,特殊情况可存储表示链表信息(表的长度等)的数据。
头结点位于链表的表头,即链表中第一个结点,其一般不存储任何数据,特殊情况可存储表示链表信息(表的长度等)的数据。
头结点的存在,其本身没有任何作用,就是一个空结点,但是在对链表的某些操作中,链表有无头结点,可以直接影响编程实现的难易程度。
例如,若链表无头结点,则对于在链表中第一个数据结点之前插入一个新结点,或者对链表中第一个数据结点做删除操作,都必须要当做特殊情况,进行特殊考虑;而若链表中设有头结点,以上两种特殊情况都可被视为普通情况,不需要特殊考虑,降低了问题实现的难度。
<strong>链表有头结点,也不一定都是有利的。例如解决约瑟夫环问题,若链表有头结点,在一定程度上会阻碍算法的实现。</strong>
**链表有头结点,也不一定都是有利的。例如解决约瑟夫环问题,若链表有头结点,在一定程度上会阻碍算法的实现。**
<strong>所以,对于一个链表来说,设置头指针是必要且必须的,但有没有头结点,则需要根据实际问题特殊分析。</strong>
**所以,对于一个链表来说,设置头指针是必要且必须的,但有没有头结点,则需要根据实际问题特殊分析。**
首元结点:指的是链表开头第一个存有数据的结点。
@@ -66,7 +66,7 @@ typedef struct Node* Link;
例如,创建一个包含头结点的链表存储 {1,2,3},如下图所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnjAoO54txAhnu7Ry8ExjGvc.png)
![](https://cdn.xyxsw.site/boxcnjAoO54txAhnu7Ry8ExjGvc.png)
## 链表的创建
@@ -95,7 +95,7 @@ Link* head = (Link*)malloc(sizeof(Link)); //创建头指针
```c
Link p;
while (Judgement) //for同理
while (Judgement) //for 同理
{
p = (Link)malloc(sizeof(Node));
p->elem = element;
@@ -104,14 +104,14 @@ while (Judgement)
}
```
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn8ZxT5oMkScArZjZhgM6TYb.png)
![](https://cdn.xyxsw.site/boxcn8ZxT5oMkScArZjZhgM6TYb.png)
### 创建结点——尾插法
```c
Link p;
Link r = (*head); //临时中间结构指针,在尾插法中始终指向最后一个结点
while (Judgement) //for同理
while (Judgement) //for 同理
{
p = (Link)malloc(sizeof(Node));
p->elem = element;
@@ -121,7 +121,7 @@ while (Judgement) //for同理
}
```
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnnMjc9pwgZgk1GBmBRlBS6d.png)
![](https://cdn.xyxsw.site/boxcnnMjc9pwgZgk1GBmBRlBS6d.png)
## 链表的基本操作
@@ -141,20 +141,20 @@ while (Judgement) //for同理
```c
#define error 0
#define ok 1
/*用e返回L中第i个数据元素的值*/
/*用 e 返回 L 中第 i 个数据元素的值*/
int GetElem(Link *L, int i; int *e)
{
Link p;
p = (*L)->next; //p指向第一个结点
p = (*L)->next; //p 指向第一个结点
int j = 1;
while (p && j < i) //p不为空或者计数器j还没有等于i时,循环继续
while (p && j < i) //p 不为空或者计数器 j 还没有等于 i 时,循环继续
{
p = p->next; //p指向下一个结点
p = p->next; //p 指向下一个结点
j++;
}
if (!p) //第i个元素不存在
if (!p) //第 i 个元素不存在
return error;
*e = p->elem; //取第i个元素的数据
*e = p->elem; //取第 i 个元素的数据
return ok;
}
```
@@ -176,19 +176,19 @@ int GetElem(Link *L, int i; int *e)
例如,在链表 `{1,2,3,4}` 的基础上分别实现在头部、中间、尾部插入新元素 5其实现过程如图所示
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnxjex5Q3Lt9AAx6roN3ClUg.png)
![](https://cdn.xyxsw.site/boxcnxjex5Q3Lt9AAx6roN3ClUg.png)
从图中可以看出,虽然新元素的插入位置不同,但实现插入操作的方法是一致的,都是先执行步骤 1 ,再执行步骤 2。实现代码如下
从图中可以看出,虽然新元素的插入位置不同,但实现插入操作的方法是一致的,都是先执行步骤 1再执行步骤 2。实现代码如下
```c
/*在L中第i个位置注意链表中的位置不一定为结点的个数之前插入新的数据元素e
L的长度加一可以用头结点存储链表长度*/
/*在 L 中第 i 个位置(注意链表中的位置不一定为结点的个数)之前插入新的数据元素 e
L 的长度加一(可以用头结点存储链表长度)*/
int ListInsert(Link *L, int i, int e)
{
Link p, r; //r为临时中间结构指针用于实现插入
p = *L; //p指向头结点
Link p, r; //r 为临时中间结构指针,用于实现插入
p = *L; //p 指向头结点
int j = 1;
while (p && j < i) //寻找第i个结点,
while (p && j < i) //寻找第 i 个结点,
{
p = p->next;
j++;
@@ -207,7 +207,7 @@ int ListInsert(Link *L, int i, int e)
对于没有头结点的链表,在头部插入结点比较特殊,需要单独实现。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn1hlL1Fk4kDK4CPT2hJxwnV.png)
![](https://cdn.xyxsw.site/boxcn1hlL1Fk4kDK4CPT2hJxwnV.png)
和 2)、3) 种情况相比,由于链表没有头结点,在头部插入新结点,此结点之前没有任何结点,实现的步骤如下:
@@ -217,8 +217,8 @@ int ListInsert(Link *L, int i, int e)
实现代码如下:
```c
/*在L中第i个位置注意链表中的位置不一定为结点的个数之前插入新的数据元素e
L的长度加一可以用头结点存储链表长度*/
/*在 L 中第 i 个位置(注意链表中的位置不一定为结点的个数)之前插入新的数据元素 e
L 的长度加一(可以用头结点存储链表长度)*/
int ListInsert(Link *L, int i, int e)
{
if (i == 1)
@@ -253,12 +253,12 @@ temp->next=temp->next->next;
例如,从存有 `{1,2,3,4}` 的链表中删除存储元素 3 的结点,则此代码的执行效果如图 3 所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnn3QHja0tzEwqJl9Mk4KnCg.png)
![](https://cdn.xyxsw.site/boxcnn3QHja0tzEwqJl9Mk4KnCg.png)
实现代码如下:
```c
/*删除L中的第i个数据元素,并用e返回其值L的长度减一
/*删除 L 中的第 i 个数据元素,并用 e 返回其值L 的长度减一
(可以用头结点存储链表长度)*/
int ListDelete(Link *L, int i, int* e)
{
@@ -271,7 +271,7 @@ int ListDelete(Link *L, int i, int* e)
j++;
}
if (!(p->next))
return error; //L中不存在第i个元素
return error; //L 中不存在第 i 个元素
r = p->next; //标记要删除的结点
p->next = r->next; //移除结点
*e = r->elem; //返回结点所存数据
@@ -282,12 +282,12 @@ int ListDelete(Link *L, int i, int* e)
对于不带头结点的链表,需要单独考虑删除首元结点的情况,删除其它结点的方式和图 3 完全相同,如下图所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnXjwE0yDFvpQxLaPw7FifxV.png)
![](https://cdn.xyxsw.site/boxcnXjwE0yDFvpQxLaPw7FifxV.png)
实现代码如下:
```c
/*删除L中的第i个数据元素,并用e返回其值L的长度减一
/*删除 L 中的第 i 个数据元素,并用 e 返回其值L 的长度减一
(可以用头结点存储链表长度)*/
int ListDelete(Link *L, int i, int* e)
{
@@ -319,7 +319,7 @@ int ListDelete(Link *L, int i, int* e)
如图所示,假设此时圆周周围有 5 个人,要求从编号为 3 的人开始顺时针数数,数到 2 的那个人出列:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcngx7ZPA7pONbJo82LbNCO1g.png)
![](https://cdn.xyxsw.site/boxcngx7ZPA7pONbJo82LbNCO1g.png)
出列顺序依次为:
@@ -329,7 +329,7 @@ int ListDelete(Link *L, int i, int* e)
- 3 出列后,从 5 开始数 12 数 2所以 2 出列;
- 最后只剩下 5 自己,所以 5 胜出。
那么,究竟要如何用链表实现约瑟夫环呢?如何让一个含 5 个元素的约瑟夫环,能从第 5 个元素出发,访问到第 2 个元素呢?上面所讲的链表操作显然是难以做到的,解决这个问题就需要用到<strong>循环链表</strong>
那么,究竟要如何用链表实现约瑟夫环呢?如何让一个含 5 个元素的约瑟夫环,能从第 5 个元素出发,访问到第 2 个元素呢?上面所讲的链表操作显然是难以做到的,解决这个问题就需要用到**循环链表**
## 循环链表
@@ -339,10 +339,10 @@ int ListDelete(Link *L, int i, int* e)
为了使空链表和非空链表处理一致,我们通常设一个头结点,当然,并不是说,循环链表一定要头结点,这需要注意。循环链表带有头结点的空链表如图所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn3l30usevMTgv1ZbZ0mfJdh.png)
![](https://cdn.xyxsw.site/boxcn3l30usevMTgv1ZbZ0mfJdh.png)
对于非空的循环链表如图所示:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcngoLTiM9wto9uCGzH7nkjkW.png)
![](https://cdn.xyxsw.site/boxcngoLTiM9wto9uCGzH7nkjkW.png)
循环链表和单链表的主要差异就在于循环的判断条件上,原来是判断 p->next 是否为空,现在则是 p->next 不等于头结点,则循环未结束。

View File

@@ -1,30 +1,30 @@
# 阶段一:编程属性
# [C 语言任务模块](https://github.com/E1PsyCongroo/HDU_C_Assignments/)
## [C 语言任务模块](https://github.com/E1PsyCongroo/HDU_C_Assignments/)
作为一名合格的大学生,更应深谙“纸上得来终觉浅,绝知此事要躬行”的道理,编程语言就像是一个工具,无论你如何熟读说明书(语法、特性),未经实践终究是靠不住的。
本模块将以有趣的任务的形式替你检测是否你已经达到了基本掌握C语言语法和一些特性的目的
本模块将以有趣的任务的形式替你检测是否你已经达到了基本掌握 C 语言语法和一些特性的目的
- 该任务模块旨在帮助巩固 C 语言基础知识,传递一些编程思维,入门学习请看 [3.4.4C 语言前置概念学习](3.4.4C%E8%AF%AD%E8%A8%80%E5%89%8D%E7%BD%AE%E6%A6%82%E5%BF%B5%E5%AD%A6%E4%B9%A0.md)
- 你可以通过使用 git `git clone ``https://github.com/E1PsyCongroo/HDU_C_Assignments.git` 获取任务
- 或者访问https://github.com/E1PsyCongroo/HDU_C_Assignments 学习
- 你可以通过使用 git 工具 `git clone https://github.com/E1PsyCongroo/HDU_C_Assignments.git` 获取任务
- 或者访问 [https://github.com/E1PsyCongroo/HDU_C_Assignments](https://github.com/E1PsyCongroo/HDU_C_Assignments) 学习
# 任务一做前必查
## 任务一做前必查
1. 理解[3.4.3解决编程问题的普适性过程](3.4.3%E8%A7%A3%E5%86%B3%E7%BC%96%E7%A8%8B%E9%97%AE%E9%A2%98%E7%9A%84%E6%99%AE%E9%80%82%E6%80%A7%E8%BF%87%E7%A8%8B.md) 。
1. 理解[3.4.3 解决编程问题的普适性过程](3.4.3%E8%A7%A3%E5%86%B3%E7%BC%96%E7%A8%8B%E9%97%AE%E9%A2%98%E7%9A%84%E6%99%AE%E9%80%82%E6%80%A7%E8%BF%87%E7%A8%8B.md) 。
2. 理解 C 语言语法基础:变量、表达式、函数、判断、循环、常用标准库函数。
3. 理解 C 语言中的一切都是数字。
4. 初步理解 C 语言各类数据类型:基本数据类型和复杂自定义数据类型。
5. 初步理解 C 语言数组及字符串。
# 任务二做前必查
## 任务二做前必查
1. 深入理解 C 语言指针、数组和字符串。
2. 理解递归思想。
3. 理解复杂自定义数据类型。
### 请阅读各个任务的 README.md了解完成任务所需的前置知识
## 请阅读各个任务的 README.md了解完成任务所需的前置知识
进阶:评价一个程序,大体分为以下四个层次。

View File

@@ -21,9 +21,9 @@ It is very dark in here.
Bye!
尽管可能微不足道,但该程序确实展示 <em>了</em>任何文本冒险中最重要的方面:描述性文本。一个好的故事是制作一款好的冒险游戏的要素之一。
尽管可能微不足道,但该程序确实展示 *了*任何文本冒险中最重要的方面:描述性文本。一个好的故事是制作一款好的冒险游戏的要素之一。
# 为什么要用英文?
## 为什么要用英文?
因为中文的编码模式可能会带来奇怪的影响。

View File

@@ -12,14 +12,14 @@
举个例子,一条林道可能隐藏着陷阱。虽然通道似乎从位置 A 通向位置 B但实际上终点是位置 C即掉进坑了。
假设我们的洞口被警卫挡住了。玩家就过不去,我们可以简单地将通道的<em>目的地</em>更改为终点位置(或 <em>NULL</em>),但这会导致对<em>诸如 go cave 和 look cave</em> 这样的命令做出不正确的回应:“你在这里看不到任何洞穴。我们需要一个将通道的实际终点和虚假终点分开的单独属性。为此,我们将引入一个属性 prospect 来表示后者。
假设我们的洞口被警卫挡住了。玩家就过不去,我们可以简单地将通道的*目的地*更改为终点位置(或 *NULL*),但这会导致对*诸如 go cave 和 look cave* 这样的命令做出不正确的回应:“你在这里看不到任何洞穴。我们需要一个将通道的实际终点和虚假终点分开的单独属性。为此,我们将引入一个属性 prospect 来表示后者。
1. 在许多冒险中,玩家以及游戏中的 NPC 在携带量方面受到限制。给每件物品一个重量,角色库存中所有物品的总重量不应超过该角色所能承载的最大重量。当然,我们也可以给一个物体一个非常高的重量,使它不可移动(一棵树,一座房子,一座山)。
2. RPG 式的冒险游戏需要角色的整个属性范围( 玩家与非玩家 ),例如 HP。HP 为零的对象要么死了,要么根本不是角色。
1. 在许多冒险中,玩家以及游戏中的 NPC 在携带量方面受到限制。给每件物品一个重量角色库存中所有物品的总重量不应超过该角色所能承载的最大重量。当然,我们也可以给一个物体一个非常高的重量,使它不可移动(一棵树,一座房子,一座山)。
2. RPG 式的冒险游戏需要角色的整个属性范围 ( 玩家与非玩家 ),例如 HP。HP 为零的对象要么死了,要么根本不是角色。
我们在 object.txt 中定义了七个新属性:
```
```c
#include <stdio.h>
#include "object.h"
@@ -115,13 +115,14 @@ extern OBJECT objs[];
textGo "Solid rock is blocking the way."
```
注意textGo 不仅对通道对象有用,而且对非通道对象也有用( 在这种情况下,以后我们将介绍“墙”这个概念)
注意textGo 不仅对通道对象有用,而且对非通道对象也有用 ( 在这种情况下以后我们将介绍“墙”这个概念)
思考题:你能否自行实现上述伪代码?
::: warning 🤔 思考题:你能否自行实现上述伪代码?
:::
现在,我们已经可以使用新属性(如果你完成了上面的思考题),<strong>details</strong> 用于新识别的命令<em>外观`<object>`</em><strong>textGo</strong> 在我们的命令 <em>go</em> 实现中替换固定文本<em>“OK</em>”。
现在,我们已经可以使用新属性 (如果你完成了上面的思考题),**details** 用于新识别的命令*外观`<object>`***textGo** 在我们的命令 *go* 实现中替换固定文本*“OK*”。
# location.c
## location.c
```c
#include <stdbool.h>
@@ -195,7 +196,7 @@ void executeGo(const char *noun)
属性权重和容量一起成为不能将某些对象移动到周围的可能原因。而 HP 检查代替了角色的硬编码白名单。
# move.c
## move.c
```c
#include <stdbool.h>
@@ -264,7 +265,7 @@ void moveObject(OBJECT *obj, OBJECT *to)
这里还有一个模块可以使用 HP 来识别角色。
# inventory.c
## inventory.c
```c
#include <stdbool.h>
@@ -327,15 +328,16 @@ void executeInventory(void)
}
```
思考题:仔细观察这段代码,看看与你写的有何不同?
::: warning 🤔 思考题:仔细观察这段代码,看看与你写的有何不同?
:::
权重检查利用了新功能 <em>weightOfContents</em>它将在<em>misc.c</em>中实现。在同一模块中,我们还对一些现有函数进行了修改,以支持最后几个属性。
权重检查利用了新功能 *weightOfContents*它将在*misc.c*中实现。在同一模块中,我们还对一些现有函数进行了修改,以支持最后几个属性。
属性内容将替换固定文本<em>“You see”。</em>在列出玩家的库存时,原始文本已经有点奇怪了,但是现在函数<em>listObjectsAtLocation</em>用于显示任何可能对象的内容(请参阅上面的函数<em>expertLook</em>),我们真的需要一些更灵活的东西。
属性内容将替换固定文本*“You see”。*在列出玩家的库存时,原始文本已经有点奇怪了,但是现在函数*listObjectsAtLocation*用于显示任何可能对象的内容(请参阅上面的函数*expertLook*),我们真的需要一些更灵活的东西。
在函数 <em>getPassage</em> 中我们将属性<em>目标</em>替换为 prospect并改进<em>对所有</em>命令(而不仅仅是 <em>go</em> and <em>look</em>)的响应,这些命令应用于位于“隐藏通道”另一端的位置。
在函数 *getPassage* 中我们将属性*目标*替换为 prospect并改进*对所有*命令(而不仅仅是 *go* and *look*)的响应,这些命令应用于位于“隐藏通道”另一端的位置。
# misc.h
## misc.h
```c
typedef enum {
@@ -357,7 +359,7 @@ extern OBJECT *actorHere(void);
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdbool.h>
@@ -432,15 +434,15 @@ int listObjectsAtLocation(OBJECT *location)
}
```
思考题:为什么上面的 getPassage 函数使用了函数指针这种语法?
::: warning 🤔 思考题:
为什么上面的 getPassage 函数使用了函数指针这种语法?
```
函数指针和指针函数有什么区别?
```
函数指针和指针函数有什么区别?
:::
为了使整个画面完整,最好扩展前面生成的地图,我们可以用虚线表示“明显”的通道。
```c
```awk
BEGIN { print "digraph map {"; }
/^- / { outputEdges(); delete a; }
/^[ \t]/ { a[$1] = $2; }
@@ -460,9 +462,9 @@ function outputEdge(from, to, style)
注意:
- 尽量不要太担心浪费仅在某些类型的对象中使用的属性上的内存空间(例如,<em>textGo</em>仅用于通道),或者许多重复的字符串文本。
- 为了演示属性 prospect 的使用,我们使洞穴无法访问。当您查看新<em>地图时,</em>这一点立即变得很明显。进入洞穴的箭头是虚线的,这意味着这是一个虚假的通道,但不是实际的通道。请放心,洞穴将在下一章重新开放。
- 请注意,更详细的描述往往需要一个更大的字典(更多的对象,更多的标签)。例如,命令 look silver coin 现在返回 "该硬币的正面有一只鹰"。玩家通过输入一个命令 look eagle 来查看银币,但程序并不知道鹰是什么意思(显然这样子是不行的)。
- 尽量不要太担心浪费仅在某些类型的对象中使用的属性上的内存空间(例如,*textGo*仅用于通道),或者许多重复的字符串文本。
- 为了演示属性 prospect 的使用,我们使洞穴无法访问。当您查看新*地图时,*这一点立即变得很明显。进入洞穴的箭头是虚线的,这意味着这是一个虚假的通道,但不是实际的通道。请放心,洞穴将在下一章重新开放。
- 请注意,更详细的描述往往需要一个更大的字典(更多的对象,更多的标签)。例如,命令 look silver coin 现在返回 "该硬币的正面有一只鹰"。玩家通过输入一个命令 look eagle 来查看银币,但程序并不知道鹰是什么意思 (显然这样子是不行的)。
输出样例

View File

@@ -7,13 +7,13 @@
让我们举一个简单的例子。为了越过守卫进入山洞,玩家必须杀死或贿赂守卫(或两者兼而有之,这很有价值)。换句话说:
- 当警卫死亡时HP=0入口开放
- 当警卫拿着银币(贿赂警卫)时,入口开放
- 当警卫拿着银币 (贿赂警卫) 时,入口开放
- 两者都不是,入口关闭
打开一个封闭的通道(在这里是进入洞穴)涉及到改变一些属性值:
- 目的地从 NULL(空地点)变为洞穴
- <strong>textGo</strong>从 "警卫阻止你...... "改为 "你走进山洞"
- 目的地从 NULL(空地点) 变为洞穴
- **textGo**从 "警卫阻止你...... "改为 "你走进山洞"
- 在一些特殊情况下,描述和细节不需要改变。但对于一个门洞或栅栏,其中之一(或两者)通常会包含一些从 "开放 "到 "关闭 "的文字。
有许多方法来实现这一目标。在这里,我们将讨论一种简单、可维护和通用的方法。
@@ -22,7 +22,7 @@
接下来,我们引入一个名为条件的新属性,它决定了某个对象是否存在。这两个通道将被赋予互斥的条件,因此在任何时候都只能有一个存在。
每个条件将被实现为一个布尔函数:<strong>TRUE</strong>意味着该对象存在,<strong>FALSE</strong>意味着它不存在。
每个条件将被实现为一个布尔函数:**TRUE**意味着该对象存在,**FALSE**意味着它不存在。
```c
bool intoCaveIsOpen(void)
@@ -36,7 +36,8 @@ bool intoCaveIsClosed(void)
}
```
思考题:你能仿照上面例子自己写一些条件函数吗?
::: warning 🤔 思考题:你能仿照上面例子自己写一些条件函数吗?
:::
新的属性条件是一个指向这样一个函数的指针。
@@ -46,9 +47,9 @@ bool (*condition)(void);
接下来,我们可以立即开始为 object.txt 中的新属性分配函数。
# object.txt
## object.txt
```
```txt
- intoCave
condition intoCaveIsOpen
description "a cave entrance to the east"
@@ -68,11 +69,12 @@ bool (*condition)(void);
textGo "The guard stops you from walking into the cave.\n"
```
思考题:尝试自己实现上面的伪代码
::: warning 🤔 思考题:尝试自己实现上面的伪代码
:::
这两个 "条件 "函数是如此具体,每一个条件函数都只用这一次。现在,我们可以在我们需要的地方定义这些函数。许多编程语言都支持匿名函数,像这样:
```
```txt
- intoCave
condition { return guard->health == 0 || silver->location == guard; }
...
@@ -84,9 +86,9 @@ bool (*condition)(void);
所以现在我们可以把额外的段落和条件添加到 object.txt 中,就像前面解释的那样。
# object.txt
## new object.txt
```
```txt
#include <stdbool.h>
#include <stdio.h>
#include "object.h"
@@ -193,11 +195,12 @@ extern OBJECT objs[];
textGo "Solid rock is blocking the way."
```
思考题:尝试自己实现这些功能,并看看与你之前设计的有何不同
::: warning 🤔 思考题:尝试自己实现这些功能,并看看与你之前设计的有何不同
:::
为了使这些条件发挥作用,我们需要调整函数 isHolding 和 getDistance。
# misc.c
## misc.c
```c
#include <stdbool.h>
@@ -273,16 +276,18 @@ int listObjectsAtLocation(OBJECT *location)
}
```
思考题:想想我们调整了什么
::: warning 🤔 思考题:想想我们调整了什么
:::
注意:
1. 警卫不可能会死,所以可以说我们的条件函数中的<strong>HP</strong>是很无用的。当然,这很容易通过添加一个 kill 命令来解决,见第 20 章。
1. 警卫不可能会死,所以可以说我们的条件函数中的**HP**是很无用的。当然,这很容易通过添加一个 kill 命令来解决,见第 20 章。
2. 这两个条件函数是互补的;它们有资格成为重复的代码。为了消除这一点,我们可能决定让一个函数调用另一个函数(用''操作符来否定结果)。一个匿名函数没有(稳定的)名字,但我们可以用它的对象来指代它。我们可以用 intoCaveBlocked 的条件函数代替。
3. 为了简单起见,条件函数没有参数。实际上,传递一个参数 OBJECT *obj 可能更好;这使得编写更多的通用条件函数成为可能,可以在多个对象中重复使用。
4. 在理论上,任何对象都可以成为 "条件"。在下一章,你可以看到一个类似的技术被应用于此。
思考题:想一想上面第二点要怎么用 C 来实现?
::: warning 🤔 思考题:想一想上面第二点要怎么用 C 来实现?
:::
输出样例

View File

@@ -1,12 +1,12 @@
# 12.开启关闭
在上一章中,我们使用 "条件 "函数来使对象消失。当然,还有一个更简单的方法来实现同样的目的:只要清除对象的位置属性就可以了!
在上一章中,我们使用 "条件 "函数来使对象消失。当然,还有一个更简单的方法来实现同样的目的:只要清除对象的位置属性就可以了
洞口是一个典型的例子,条件函数在那里工作得特别好。这是因为入口受到其他对象(守卫和银币)中的属性的影响;我们可以使用函数使得所有的逻辑都能保持一致。
让我们举一个更直接的例子。假设山洞有一扇门通向一个密室。只是一个简单的门洞,玩家可以打开和关闭。就像前一章一样,我们将使用两个对象来表示这个通道;一个表示打开的门,另一个表示门关闭时。
```
```txt
- backroom
description "a backroom"
tags "backroom"
@@ -28,11 +28,12 @@
textGo "The door is closed.\n"
```
思考题:尝试自己用 C 语言实现
::: warning 🤔 思考题:尝试自己用 C 语言实现
:::
自然,门也应该能从另一侧进入。
```
```txt
- openDoorToCave
description "an open door to the north"
tags "north", "door", "doorway"
@@ -111,7 +112,8 @@ else
}
```
思考题:你能不能仿照上面的代码实现 close 功能?
::: warning 🤔 思考题:你能不能仿照上面的代码实现 close 功能?
:::
为了使事情稍微复杂一些,我们可以在门上或盒子上加一把锁。这需要(至少)三个相互排斥的对象;每个可能的状态都有一个:打开、关闭和锁定。但是我们仍然可以使用同一个函数来交换对象的位置。例如,这里是如何解锁一个上锁的盒子;反之亦然。
@@ -132,15 +134,17 @@ else if (obj == lockedBox)
显然,代码的行数与游戏中的门(以及盒子和其他可以打开的物体)的数量成正比。因此,如果你的游戏有不止几扇门,那么选择一个更通用的解决方案是个好主意。顺便说一下,这对每一个命令都是适用的:当它涉及到许多物体时,尽量写通用代码;但当你处理一两个特殊情况时,就坚持使用直接的、专门的代码。
思考题:我们可以使用什么方法来解决这个问题?
::: warning 🤔 思考题:
我们可以使用什么方法来解决这个问题?
提示C++ 中的模板功能(这只是一种选择)
下面我们将揭晓答案
:::
通用代码通常带有数据驱动的方法。换句话说,我们需要向我们的对象结构添加一个或多个属性。在这种特殊情况下,我们将为我们希望支持的每个命令添加一个函数指针:打开、关闭、锁定和解锁。
# object.txt
## object.txt
```c
#include <stdbool.h>
@@ -354,7 +358,7 @@ extern OBJECT objs[];
为了避免重复的代码,我们这次特意没有使用匿名函数。相反,我们将在一个单独的模块中实现必要的逻辑。函数 swapLocations 也在其中,这不过是一个稍微扩展的版本,它也会向用户输出反馈。
# toggle.h
## toggle.h
```c
extern void cannotBeOpened(void);
@@ -376,7 +380,7 @@ extern void toggleBox(void);
extern void toggleBoxLock(void);
```
# toggle.c
## toggle.c
```c
#include <stdbool.h>
@@ -439,7 +443,7 @@ void toggleBoxLock(void)
正如前面所宣布的,打开、关闭、锁定和解锁这四个命令的实现是完全通用的。
# openclose.h
## openclose.h
```c
extern void executeOpen(const char *noun);
@@ -448,7 +452,7 @@ extern void executeLock(const char *noun);
extern void executeUnlock(const char *noun);
```
# openclose.c
## openclose.c
```c
#include <stdbool.h>
@@ -478,17 +482,18 @@ void executeUnlock(const char *noun)
{
OBJECT *obj = reachableObject("what you want to unlock", noun);
if (obj != NULL) (*obj->unlock)();
}
```
上面,我们使用了一个通用函数 reachableObject 来处理不在这里的对象;其实现见下文。这样,我们就不必把同样的代码写四遍(每个执行函数写一遍)。更多的命令将在第 15 章中加入;这些命令将受益于同样的函数。
# reach.h
## reach.h
```c
extern OBJECT *reachableObject(const char *intention, const char *noun);
```
# reach.c
## reach.c
```c
#include <stdbool.h>
@@ -526,7 +531,7 @@ OBJECT *reachableObject(const char *intention, const char *noun)
同样,我们也要对 parsexec.c 进行补充
# parsexec.c
## parsexec.c
```c
#include <stdbool.h>

View File

@@ -1,6 +1,6 @@
# 13.编写解析器
每个文本冒险都有一个解析器,但是解析器也有高下之分。一个简单的 "动词-名词 "解析器(就像我们从第二章开始一直使用的那个)对于一个精心设计的冒险游戏来说可能已经足够了。
每个文本冒险都有一个解析器,但是解析器也有高下之分。一个简单的 "动词 - 名词 "解析器(就像我们从第二章开始一直使用的那个)对于一个精心设计的冒险游戏来说可能已经足够了。
然而Infocom 已经证明,一个更高级的解析器确实有助于制作一个令人愉快的游戏。它不一定要通过图灵测试。
@@ -19,7 +19,8 @@ char *noun = strtok(NULL, "\n");
- 它确实接受多字对象(如银币),但字与字之间的空格必须准确无误。我们的游戏拒绝银币和硬币之间的双空格。
- 它是区分大小写的;"向北走 "的命令因为大写的 "G "而不被识别。
思考题:你能想到有什么办法解决这些问题吗?
::: warning 🤔 思考题:你能想到有什么办法解决这些问题吗?
:::
编写一个好的分析器并不是一件小事,但在这里我将给你一个相对简单的方法,我们将定义一个由模式列表组成的语法,类似于(但比)正则表达式要简单得多。
@@ -30,7 +31,8 @@ char *noun = strtok(NULL, "\n");
为了解析用户的输入,我们将从上到下遍历模式列表,依次尝试将用户的输入与每个模式匹配。我们将在发现第一个匹配时停止。为了简单起见,我们将不使用回溯,尽管这可以在以后添加。
思考题:如果我们使用回溯,那该怎么编写代码?
::: warning 🤔 思考题:如果我们使用回溯,那该怎么编写代码?
:::
大写字母是我们语法中的非终端符号,它们可以匹配任何标签(任何对象)。当解析器在两个不同的标签(例如 "银币 "和 "银")之间进行选择时,较长的标签将被优先考虑。
@@ -40,7 +42,7 @@ char *noun = strtok(NULL, "\n");
const char *params[26];
```
该数组有 26 个元素;字母表中的每个(大写)字母都有一个,这足以满足一个模式中多达 26 个不同的非终端。对于一个(匹配的)模式中的每个非终端,将通过在非终端的数组元素中填充一个指向该特定标签的指针来 "捕获 "一个匹配的标签。 params[0](第一个数组元素)捕获非终端 "A"params[1]捕获 "B",以此类推。一个简单的宏定义可以用来找到属于某个非终端的数组元素。
该数组有 26 个元素;字母表中的每个(大写)字母都有一个,这足以满足一个模式中多达 26 个不同的非终端。对于一个(匹配的)模式中的每个非终端,将通过在非终端的数组元素中填充一个指向该特定标签的指针来 "捕获 "一个匹配的标签。params[0](第一个数组元素)捕获非终端 "A"params[1]捕获 "B",以此类推。一个简单的宏定义可以用来找到属于某个非终端的数组元素。
```c
#define paramByLetter(letter) (params + (letter) - 'A')
@@ -52,7 +54,8 @@ const char *params[26];
假设用户打错了字,输入了 "go kave"。问题是,这个命令到底应不应该匹配 "go A "这个命令?如果我们不想出解决办法,那么这个命令将无法匹配任何其他命令,并最终进入一个通用的错误处理程序,它可能会回答 "我不知道如何去 kave "这样的话。这就失去了改进这些 "消极反应 "的所有机会;回答 "我不知道你要去哪里 "已经感觉更自然了。最好的办法是将所有关于命令去向的答复保持在函数 executeGo 内。
停下来想一想,可以怎么解决这个问题?
::: warning 🤔 停下来想一想,可以怎么解决这个问题?
:::
有几种方法可以实现这一点,但最简单的方法是允许非终止符匹配任何东西。所以不仅仅是一个有效的标签,也包括完全的胡言乱语、空白或什么都没有这种语句。这种 "无效 "的输入将被捕获为一个空字符串("")。
@@ -73,17 +76,18 @@ const char *params[26];
前两个命令形式可以为任何顺序,但第三个必须在最后。
思考题:你是否有办法解决这个问题?
::: warning 🤔 思考题:你是否有办法解决这个问题?
:::
是时候将其付诸行动了。我们将抛弃模块 parsexec.c 的现有内容,用一个新的函数 parseAndExecute 的实现来取代它,该函数使用一个模式列表,应该能够匹配我们到目前为止实现的每一条命令。每个模式都与一个执行相应命令的函数相联系。
# parsexec.c
## parsexec.c
```c
extern bool parseAndExecute(const char *input);
```
# parsexec.h
## parsexec.h
```c
#include <ctype.h>
@@ -149,7 +153,7 @@ bool parseAndExecute(const char *input)
最难的部分是函数 matchCommand 的实现。但正如你在下面看到的,这也可以在不到 100 行的代码中完成。
# match.h
## match.h
```c
#define MAX_PARAMS 26
@@ -161,7 +165,7 @@ extern const char *params[];
extern bool matchCommand(const char *src, const char *pattern);
```
# match.c
## match.c
```c
#include <ctype.h>
@@ -242,7 +246,7 @@ bool matchCommand(const char *src, const char *pattern)
我们调整各种命令的实现,以利用新的数组参数。
# <strong>inventory.h</strong>
## **inventory.h**
```c
extern bool executeGet(void);
@@ -252,7 +256,7 @@ extern bool executeGive(void);
extern bool executeInventory(void);
```
# <strong>inventory.c</strong>
## **inventory.c**
```c
#include <stdbool.h>
@@ -323,7 +327,7 @@ bool executeInventory(void)
我们在上一章中添加的模块也是如此。
# opemclose.h
## opemclose.h
```c
extern bool executeOpen(void);
@@ -332,7 +336,7 @@ extern bool executeLock(void);
extern bool executeUnlock(void);
```
# openclose.c
## openclose.c
```c
#include <stdbool.h>
@@ -372,7 +376,7 @@ bool executeUnlock(void)
在 location.c 中look around 命令被赋予了自己的功能,与检查特定对象的 look 命令分开(见第 7-12 行)。
# location.h
## location.h
```c
extern bool executeLookAround(void);
@@ -380,7 +384,7 @@ extern bool executeLook(void);
extern bool executeGo(void);
```
# location.c
## location.c
```c
#include <stdbool.h>
@@ -453,7 +457,7 @@ bool executeGo(void)
}
```
我们的游戏仍然只接受简单的动词-名词命令,但新的解析器确实有可能接受有多个名词的命令,如 "put coin in box",这将在下一章中演示。
我们的游戏仍然只接受简单的动词 - 名词命令,但新的解析器确实有可能接受有多个名词的命令,如 "put coin in box",这将在下一章中演示。
新的解析器比原来的解析器有了很大的改进,但以今天的标准来看,它仍然远远不够完美。例如,没有结构性的方法可以用一个命令操纵多个对象("获得硬币、钥匙和灯")或连续执行两个或多个命令("获得钥匙然后向东走")。这对于一个 RPG 游戏来说限制实在太大了!

View File

@@ -2,7 +2,7 @@
是时候证明新的解析器确实有能力解释更复杂的命令了。
到目前为止,我们的解析器只接受简单的动词-名词命令。让我们试着解析一些更复杂的命令,比如:
到目前为止,我们的解析器只接受简单的动词 - 名词命令。让我们试着解析一些更复杂的命令,比如:
- get coin from box
- put coin in box
@@ -16,7 +16,8 @@
- ask A from B
- give A to B
思考题:你能否自行实现这些命令
::: warning 🤔 思考题:你能否自行实现这些命令
:::
但是正如前一章所解释的,类似的命令(比如 "从 B 中获取 A "和已经存在的 "获取 A")必须以正确的顺序排列。如果'get A'首先出现,那么它将消耗任何以'get'开头的命令,包括所有应该被新模式匹配的命令。简而言之,"从 B 获取 A "必须出现在 "获取 A "之前。
@@ -32,13 +33,13 @@
目前,我们不需要有两个以上非终结点的模式。
# parsexec.h
## parsexec.h
```c
extern bool parseAndExecute(const char *input);
```
# parsexec.c
## parsexec.c
```c
#include <ctype.h>
@@ -106,9 +107,9 @@ bool parseAndExecute(const char *input)
}
```
在一个新的模块 inventory2.c 中,我们实现了新的多名词命令 get、drop/put、ask 和 give。现在我们终于可以把金币放回盒子里了(可喜可贺,可喜可贺)。
在一个新的模块 inventory2.c 中,我们实现了新的多名词命令 get、drop/put、ask 和 give。现在我们终于可以把金币放回盒子里了 (可喜可贺,可喜可贺)。
# inventory2.h
## inventory2.h
```c
extern bool executeGetFrom(void);
@@ -117,7 +118,7 @@ extern bool executeAskFrom(void);
extern bool executeGiveTo(void);
```
# inventory2.c
## inventory2.c
```c
#include <stdbool.h>
@@ -210,11 +211,12 @@ bool executeGiveTo(void)
仔细观察上面的代码,你可能会注意到,像 "把硬币放进森林 "和 "把硬币放进盒子 "这样的命令(当盒子被关闭时)会得到以下奇怪的回答:"这太重了。" 这是因为大多数物体(包括封闭的盒子,以及像森林这样的场景)容纳其他物体的能力为零。这是正确的,但这个信息是很不恰当的。为了避免这种情况,我们将为那些容量为零的物体引入一个单独的信息:"这样做似乎不太适合。"
先想想有没有什么办法解决?
::: warning 🤔 先想想有没有什么办法解决?
:::
然而,当它作为对 "把钥匙放进盒子里 "的回应时,这个特殊的信息是完全误导的。所以我们将为这种特殊的对象组合做一个特殊的例外。
# move.c
## move.c
```c
#include <stdbool.h>

View File

@@ -4,11 +4,11 @@
在黑暗中的效果因游戏而异。通常情况下,它使命令 "look "没有效果。在一些游戏中(如 Zork黑暗是致命的。在其他游戏中只要你画出了黑暗区域的详细地图在没有光源的情况下你仍然可以取得进展。
我们的游戏将保持在这两者之间;在黑暗中不会让你被杀,但你也不能进入任何通道(具有光亮的通道将是一个例外)。对我们来说,让玩家跑进一个黑暗的区域,而没有不让他机会回到他来的地方,似乎是不公平的。
我们的游戏将保持在这两者之间;在黑暗中不会让你被杀,但你也不能进入任何通道 (具有光亮的通道将是一个例外)。对我们来说,让玩家跑进一个黑暗的区域,而没有不让他机会回到他来的地方,似乎是不公平的。
好吧,所以首先,我们来设计在黑暗中玩家无法看到周围环境。
# location.c
## location.c
```c
#include <stdbool.h>
@@ -90,7 +90,7 @@ bool executeGo(void)
其次,在黑暗中玩家无法看到或使用附近的物体。
# noun.c
## noun.c
```c
#include <stdbool.h>
@@ -193,7 +193,7 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
在这两种情况下,我们都使用了一个函数 isLit。它在 misc.c 中被定义(并且使用量增多了)。
# misc.h
## misc.h
```c
typedef enum {
@@ -216,7 +216,7 @@ extern OBJECT *actorHere(void);
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdbool.h>
@@ -318,6 +318,7 @@ int listObjectsAtLocation(OBJECT *location)
}
}
return count;
}
```
注意:
@@ -326,13 +327,14 @@ int listObjectsAtLocation(OBJECT *location)
- isNoticeable 函数相比 isLit 更进一步。它对每个物体都有效,而不仅仅是地点和灯。它还考虑到玩家库存中的物体总是可以被使用,即使是在黑暗中。
- 第 60 行:附近的物体仍然隐藏在黑暗中,被视为'不在这里'。这自然可以防止游戏泄露玩家不应该知道的物体的信息。
思考题:你还能想到那哪些可以改进的地方吗?
::: warning 🤔 思考题:你还能想到那哪些可以改进的地方吗?
:::
我们为实现 isLit 函数的功能从而使用了一个新的属性 light。
# object.awk
## object.awk
```
```awk
BEGIN {
count = 0;
obj = "";
@@ -428,11 +430,11 @@ function outputRecord(separator)
}
```
默认情况下,亮度为零意味着一个物体不发光。在大白天的每一个地点(通常是除了地下的所有地点)都会被赋予一个正(大于 0)的光线值。其实是什么值并不重要,只要它不是零就可以了。我们还将添加一盏灯,玩家可以携带它来穿越黑暗区域。
默认情况下,亮度为零意味着一个物体不发光。在大白天的每一个地点(通常是除了地下的所有地点)都会被赋予一个正 (大于 0) 的光线值。其实是什么值并不重要,只要它不是零就可以了。我们还将添加一盏灯,玩家可以携带它来穿越黑暗区域。
# object.txt
## object.txt
```
```txt
#include <stdbool.h>
#include <stdio.h>
#include "object.h"
@@ -658,7 +660,7 @@ extern OBJECT objs[];
我们将添加一些命令,我们可以用来打开和关闭灯。
# parsexec.c
## parsexec.c
```c
#include <ctype.h>
@@ -733,14 +735,14 @@ bool parseAndExecute(const char *input)
下面是这些命令的实现。
# onoff.h
## onoff.h
```c
extern bool executeTurnOn(void);
extern bool executeTurnOff(void);
```
# onoff.c
## onoff.c
```c
#include <stdbool.h>
@@ -789,7 +791,7 @@ bool executeTurnOff(void)
为了打开和关闭灯,我们将使用我们用来打开和关闭门和盒子的相同技巧(见第 13 章)。
# toggle.h
## toggle.h
```c
extern void cannotBeOpened(void);
@@ -813,7 +815,7 @@ extern void toggleBoxLock(void);
extern void toggleLamp(void);
```
# toggle.c
## toggle.c
```c
#include <stdbool.h>
@@ -895,9 +897,9 @@ void toggleLamp(void)
最后,我们将在我们生成的地图上标记出黑暗的位置。
# map.awk
## map.awk
```c
```awk
BEGIN { print "digraph map {\n\tnode [style=filled]"; }
/^- / { outputEdges(); obj = $2; delete a; }
/^[ \t]/ { a[$1] = $2; }
@@ -929,9 +931,10 @@ function outputNodes()
}
```
思考题:尝试将上面的伪代码用 C 语言实现其功能
::: warning 🤔 思考题:尝试将上面的伪代码用 C 语言实现其功能
:::
玩家们,请注意不要把灯关掉,也不要把它丢掉。如果这样做,那么在黑暗中你将永远无法找回它。换言之,你会被困在黑暗之中! 幸运的是,下一章将提供一个撤销笨拙行动的方法。
玩家们,请注意不要把灯关掉,也不要把它丢掉。如果这样做,那么在黑暗中你将永远无法找回它。换言之,你会被困在黑暗之中幸运的是,下一章将提供一个撤销笨拙行动的方法。
输出样例Welcome to Little Cave Adventure.
You are in an open field.

View File

@@ -1,26 +1,24 @@
# 2.探索未知
::: tip 提醒
::: tip <font size=5>**驾驭项目,而不是被项目驾驭**</font>
# <strong> 驾驭项目, 而不是被项目驾驭</strong>
你和一个项目的关系会经历 4 个阶段:
你和一个项目的关系会经历 4 个阶段:
1. 被驾驭:你对它一无所知
2. 一知半解:你对其中的主要模块和功能有了基本的了解
3. 驾轻就熟:你对整个项目的细节都了如指掌
4. 为你所用:你可以随心所欲地在项目中添加你认为有用的功能
1. 被驾驭: 你对它一无所知
2. 一知半解: 你对其中的主要模块和功能有了基本的了解
3. 驾轻就熟: 你对整个项目的细节都了如指掌
4. 为你所用: 你可以随心所欲地在项目中添加你认为有用的功能
如果你想要达成第二个阶段,你需要仔细学习不断探索更新的内容,达到第三个阶段的主要手段是独立完成实验内容和独立调试。至于要达到第四个阶段,就要靠你的主观能动性了:代码还有哪里做得不够好?怎么样才算是够好?应该怎么做才能达到这个目标?
如果你想要达成第二个阶段,你需要仔细学习不断探索更新的内容, 达到第三个阶段的主要手段是独立完成实验内容和独立调试. 至于要达到第四个阶段, 就要靠你的主观能动性了: 代码还有哪里做得不够好? 怎么样才算是够好? 应该怎么做才能达到这个目标?
你毕业后到了工业界或学术界,就会发现真实的项目也都是这样:
你毕业后到了工业界或学术界, 就会发现真实的项目也都是这样:
1. 刚接触一个新项目, 不知道如何下手
1. 刚接触一个新项目,不知道如何下手
2. RTFM, RTFSC, 大致明白项目组织结构和基本的工作流程
3. 运行项目的时候发现有非预期行为(可能是配置错误或环境错误, 可能是和已有项目对接出错, 也可能是项目自身的 bug), 然后调试. 在调试过程中, 对这些模块的理解会逐渐变得清晰.
4. 哪天需要你在项目中添加一个新功能, 你会发现自己其实可以胜任.
3. 运行项目的时候发现有非预期行为 (可能是配置错误或环境错误可能是和已有项目对接出错也可能是项目自身的 bug), 然后调试在调试过程中对这些模块的理解会逐渐变得清晰
4. 哪天需要你在项目中添加一个新功能你会发现自己其实可以胜任
这说明了: 如果你一遇到 bug 就找大神帮你调试, 你失去的机会和能力会比你想象的多得多
这说明了如果你一遇到 bug 就找大神帮你调试你失去的机会和能力会比你想象的多得多
:::
文字冒险游戏的基本交互很简单
@@ -31,17 +29,17 @@
那么,当命令很多的时候,如果你将他写在一起,一个文件有五六千行,我相信这样的情况你是不愿意去看的,因此,我们引入了函数的概念。
自行了解函数的概念,同时去了解当我需要引用别的文件的函数时该怎么办?
了解一下什么是“驼峰原则”,我们为什么要依据它命名函数?
::: warning 🤔 自行了解函数的概念,同时去了解当我需要引用别的文件的函数时该怎么办?
了解一下什么是“驼峰原则”,我们为什么要依据它命名函数?
:::
下面的代码示例包含三个函数,每个步骤一个函数:
1. 函数<em>getInput</em>
2. 函数<em>parseAndExecute</em>
3. 函数<em>main</em>,负责重复调用其他两个函数。
1. 函数*getInput*
2. 函数*parseAndExecute*
3. 函数*main*,负责重复调用其他两个函数。
# main.c
## main.c
```c
#include <stdbool.h>
@@ -55,7 +53,7 @@ static bool getInput(void)
printf("\n--> ");
//你可以将他改成你喜欢的内容
return fgets(input, sizeof input, stdin) != NULL;
//fgets用于收集键盘的输入
//fgets 用于收集键盘的输入
}
int main()
@@ -69,23 +67,26 @@ int main()
注意:某些老版本的 C 语言不支持 bool 选项,你将他改为 int 是一样的。
思考题static 是什么意思?我为什么要用他?
::: warning 🤔 思考题static 是什么意思?我为什么要用他?
:::
# <strong>parsexec.h</strong>
## **parsexec.h**
```c
extern bool parseAndExecute(char *input);
```
思考题:extern 是干什么的?.h 文件又在干嘛?
::: warning 🤔 思考题:
extern 是干什么的?.h 文件又在干嘛?
我用了一个指针input 前面是个指针!!!
指针是啥?[C 指针详解](https://www.runoob.com/w3cnote/c-pointer-detail.html) STFW虽然都给你了
在这里用指针是为了传参的时候可以传字符串哦
:::
# <strong>parsexec.c</strong>
## **parsexec.c**
```c
#include <stdbool.h>
@@ -97,11 +98,11 @@ bool parseAndExecute(char *input)
{
char *verb = strtok(input, " \n");
char *noun = strtok(NULL, " \n");
//strtokstring库下的一个函数
//strtokstring 库下的一个函数
if (verb != NULL)
{
if (strcmp(verb, "quit") == 0)
//strcmp也是
//strcmp 也是
{
return false;
}
@@ -116,18 +117,20 @@ bool parseAndExecute(char *input)
else
{
printf("I don't know how to '%s'.\n", verb);
//%s是verb附加参数的占位符
//%s是 verb 附加参数的占位符
}
}
return true;
}
```
你的编译器可能会给出警告 the unused variable noun这些不用担心将会在下一章解决。
你的编译器可能会给出警告 the unused variablenoun这些不用担心将会在下一章解决。
返回<em>false</em>将导致主循环结束。
返回*false*将导致主循环结束。
RTFM&&STFW 搞懂 strtok 和 strcmp 的用法
::: warning <font size=5>**RTFM&&STFW**</font>
搞懂 strtok 和 strcmp 的用法
:::
考虑一下 NULL 是干什么的

View File

@@ -1,12 +1,12 @@
# 3.指明地点
某种极其糟糕的编程习惯
# Copy-paste
::: warning <font size=5>某种极其糟糕的编程习惯</font>
<font size=5><strong>Copy-paste</strong></font>
我们很多同学在编程的过程中,可能会写出一大堆重复性很强的代码,在最近看的 pa 中,举了这样一个例子,你不需要看懂只需要感受到就可:
:::
```
```c
if (strcmp(s, "$0") == 0)
return cpu.gpr[0]._64;
else if (strcmp(s, "ra") == 0)
@@ -86,19 +86,20 @@ bx = torch.cat((xs[0], bs[0], xs[1], bs[1], xs[2], bs[2], xs[3], bs[3], xs[4], b
xs[24], bs[24], xs[25], bs[25], xs[26], bs[26], xs[27], bs[27], xs[28], bs[28], xs[29], bs[29], xs[30], bs[30], xs[31], bs[31]), 1)
```
你想想,你遇到这么长的代码,你愿意看他吗?
::: tip <font size=5>你想想,你遇到这么长的代码,你愿意看他吗?</font>
更可怕的是,这种编码模式可能会导致意想不到的 bug。
当你发现这些代码有 bug 的时候, 噩梦才刚刚开始. 也许花了好几天你又调出一个 bug 的时候, 才会想起这个 bug 你好像之前在哪里调过. 你也知道代码里面还有类似的 bug, 但你已经分辨不出哪些代码是什么时候从哪个地方复制过来的了.
当你发现这些代码有 bug 的时候噩梦才刚刚开始也许花了好几天你又调出一个 bug 的时候才会想起这个 bug 你好像之前在哪里调过你也知道代码里面还有类似的 bug, 但你已经分辨不出哪些代码是什么时候从哪个地方复制过来的了
这种糟糕的编程习惯叫 Copy-Paste, 经过上面的分析, 相信你也已经领略到它的可怕了. 事实上, [周源源教授](https://cseweb.ucsd.edu/~yyzhou/)的团队在 2004 年就设计了一款工具 CP-Miner, 来自动检测操作系统代码中由于 Copy-Paste 造成的 bug. 这个工具还让周源源教授收获了一篇[系统方向顶级会议 OSDI 的论文](http://pages.cs.wisc.edu/~shanlu/paper/OSDI04-CPMiner.pdf), 这也是她当时所在学校 UIUC 史上的第一篇系统方向的顶级会议论文.
这种糟糕的编程习惯叫 Copy-Paste, 经过上面的分析相信你也已经领略到它的可怕了事实上[周源源教授](https://cseweb.ucsd.edu/~yyzhou/)的团队在 2004 年就设计了一款工具 CP-Miner, 来自动检测操作系统代码中由于 Copy-Paste 造成的 bug. 这个工具还让周源源教授收获了一篇[系统方向顶级会议 OSDI 的论文](http://pages.cs.wisc.edu/~shanlu/paper/OSDI04-CPMiner.pdf), 这也是她当时所在学校 UIUC 史上的第一篇系统方向的顶级会议论文
后来周源源教授发现, 相比于操作系统, 应用程序的源代码中 Copy-Paste 的现象更加普遍. 于是她们团队把 CP-Miner 的技术应用到应用程序的源代码中, 并创办了 PatternInsight 公司. 很多 IT 公司纷纷购买 PatternInsight 的产品, 并要求提供相应的定制服务, 甚至 PatternInsight 公司最后还被 VMWare 收购了.
后来周源源教授发现相比于操作系统应用程序的源代码中 Copy-Paste 的现象更加普遍于是她们团队把 CP-Miner 的技术应用到应用程序的源代码中并创办了 PatternInsight 公司很多 IT 公司纷纷购买 PatternInsight 的产品并要求提供相应的定制服务甚至 PatternInsight 公司最后还被 VMWare 收购了
这个故事折射出, 大公司中程序员的编程习惯也许不比你好多少, 他们也会写出 Copy-Paste 这种难以维护的代码. 但反过来说, 重视编码风格这些企业看中的能力, 你从现在就可以开始培养.
这个故事折射出大公司中程序员的编程习惯也许不比你好多少他们也会写出 Copy-Paste 这种难以维护的代码但反过来说重视编码风格这些企业看中的能力你从现在就可以开始培养
:::
<em>传统上,文本冒险是由(许多)不同位置组成的虚拟世界。虽然这不是必需的(一些冒险发生在一个房间里!),但这是解释</em><em>数据结构</em><em>使用的好方法。</em>
*传统上,文本冒险是由(许多)不同位置组成的虚拟世界。虽然这不是必需的(一些冒险发生在一个房间里!),但这是解释**数据结构**使用的好方法。*
我们首先定义一个[结构](http://en.wikipedia.org/wiki/Struct_(C_programming_language))来表示一个位置。它包含两个简单的属性开始(稍后可能会有更多的属性)。
@@ -112,13 +113,13 @@ struct location {
};
```
思考题:我们为什么要用结构体来保存位置?
::: warning 🤔 思考题:
我们为什么要用结构体来保存位置?
```
这样子做有什么好处?
```
const 又是什么?
const 又是什么?
:::
接下来,我们定义一个位置数组。目前,我们保持它非常简单:只有两个位置。
@@ -135,9 +136,9 @@ struct location locs[2] = {
};
```
让我们把它付诸实践。在上一章 <em>parsexec.c</em> 的代码示例中,我们更改了第 4、18 和 22 行)。
让我们把它付诸实践。在上一章*parsexec.c* 的代码示例中,我们更改了第 4、18 和 22 行)。
# <strong>parsexec.c</strong>
## <strong>parsexec.c</strong>
```c
#include <stdbool.h>
@@ -174,14 +175,14 @@ bool parseAndExecute(char *input)
接下来,我们将一个新模块添加到项目中
# <strong>location.h</strong>
## <strong>location.h</strong>
```c
extern void executeLook(const char *noun);
extern void executeGo(const char *noun);
```
# <strong>location.c</strong>
## <strong>location.c</strong>
```c
#include <stdio.h>
@@ -236,9 +237,9 @@ void executeGo(const char *noun)
}
```
在 C 语言中,你可以使用单个语句来定义类型(<em>结构位置</em>),声明变量(<em>locs</em>)并用其初始值填充它。
在 C 语言中,你可以使用单个语句来定义类型(*结构位置*),声明变量(*locs*)并用其初始值填充它。
思考题:变量<em>locs</em>是[静态分配的](http://en.wikipedia.org/wiki/Static_memory_allocation),什么是静态分配?
思考题:变量*locs*是[静态分配的](http://en.wikipedia.org/wiki/Static_memory_allocation),什么是静态分配?
静态分配和动态分配有什么不同之处?

View File

@@ -1,17 +1,17 @@
# 4.创建对象
<em>在我们继续之前,我</em><em>们</em><em>在这里使用的是</em><em>哲学意义上</em><em>的“对象”一词。它与</em><em>面向对象编程</em><em>无关,也与</em><em>Java</em><em></em><em>C#</em><em>和</em><em>Python</em><em>等编程语言中预定义的“对象”类型没有任何共同之处。下面,我将定义一个名为 object 的</em><em>结构体。。</em>
*在我们继续之前,我们在这里使用的是[哲学意义上](https://en.wikipedia.org/wiki/Object_(philosophy))的“对象”一词。它与[面向对象编程](https://en.wikipedia.org/wiki/Object-oriented_programming)无关也与JavaC#和Python等编程语言中预定义的“对象”类型没有任何共同之处。下面,我将定义一个名为 object 的结构体。*
冒险游戏中的大多数谜题都围绕着<strong>物品</strong>。例子:
冒险游戏中的大多数谜题都围绕着**物品**。例子:
- 必须找到一把钥匙,然后用来解锁某扇门。
- 必须杀死守卫或者诱骗守卫才能开启房间
所以,为了表示这个物品,我们可以使用如下[结构](http://en.wikipedia.org/wiki/Struct_(C_programming_language))
- <strong>description: </strong><strong>对物品的描述</strong>
- <strong>tag: </strong><strong>物品的类型</strong>
- <strong>location: </strong><strong>物品所在</strong><strong>的位置。这是</strong><strong>对应</strong><strong>上一章中定义的</strong><strong>物品</strong><strong>位置</strong><strong>的指针。</strong>
- **\*description: 对物品的描述**
- **\*tag: 物品的类型**
- **\*location: 物品所在的位置。这是对应上一章中定义的物品位置的指针。**
```c
struct object {
@@ -47,9 +47,11 @@ objs[] = {
我们发现 OBJECT 的结构体里面有一个指针和自己长得一样,不用担心,这和链表的操作类似。
思考题:链表是什么,为什么要有这么一个操作指针?
::: warning 🤔 思考题:
链表是什么,为什么要有这么一个操作指针?
链表和数组有什么异同点,他们分别在增删改查上有什么优劣?
:::
为了更容易地用那些所谓的物品或者是地点,我们将为每个元素定义一个名字
@@ -80,33 +82,35 @@ for (obj = objs; obj < objs + 5; obj++)
}
```
暂停理解一下吧
::: warning 🤔 暂停理解一下吧
:::
那么,我们有合并这个物品(或地点)列表有什么好处呢?答案是这会让我们的代码变得更加简单,因为许多函数(如上面的函数通过这样的列表)只需要扫描单个列表就可以实现,而不是三个列表。有人可能会说没必要,因为每个命令仅适用于一种类型的对象:
- 命令 <em>go</em> 适用于位置对象。
- 命令 <em>get</em> 应用于获得物品。
- 命令 *go* 适用于位置对象。
- 命令 *get* 应用于获得物品。
- 命令 kill 适应用于杀死人物。
但这种方法不太对劲,原因有三:
1. 某些命令适用于多种类型的对象,尤其是<em>检查</em>
1. 某些命令适用于多种类型的对象,尤其是*检查*
2. 有时候会出现很没意思的交互方式,比如说你要吃掉守卫,他说不行。
3. 某些对象在游戏中可能具有多个角色。比如说队友系统NPC 可以是你的物品也可以是对象
将所有对象放在一个大列表中很容易添加一个名为“type”的属性来<em>构造对象</em>,以帮助我们区分不同类型的对象。
将所有对象放在一个大列表中很容易添加一个名为“type”的属性来*构造对象*,以帮助我们区分不同类型的对象。
怎么做怎么遍历呢?先思考吧
::: warning 🤔 怎么做怎么遍历呢?先思考吧
:::
但是,对象通常具有同样有效的其他特征:
- <strong>Locations 通过</strong><strong>道路</strong><strong>连接(将在后面介绍)。如果一个物体无法通过一条通道到达,那么它就不是一个位置。就是这么简单。</strong>
- <strong>Items玩家唯一可以捡起的物品;</strong><strong>可以给他们整一个重量的属性</strong>
- <strong>Actors玩家唯一可以与之交谈交易战斗的对象;当然,前提是他们还活着!</strong><strong>可以加一个 HP 属性</strong>
- **Locations通过道路连接(将在后面介绍)。如果一个物体无法通过一条通道到达,那么它就不是一个位置。就是这么简单。**
- **Items玩家唯一可以捡起的物品;可以给他们整一个重量的属性**
- **Actors玩家唯一可以与之交谈交易战斗的对象;当然,前提是他们还活着!可以加一个 HP 属性**
我们还要向数组中添加一个对象:玩家自己。
在上一章中,有一个单独的变量 <em>locationOfPlayer</em>。我们将删除它,然后换上用户的位置属性取代他!
在上一章中,有一个单独的变量 *locationOfPlayer*。我们将删除它,然后换上用户的位置属性取代他!
例如,此语句会将玩家移入洞穴:
@@ -122,7 +126,7 @@ player->location->description
是时候把它们放在一起了。我们从对象数组的全新模块开始
# Object.h
## Object.h
```c
typedef struct object {
@@ -143,7 +147,7 @@ extern OBJECT objs[];
#define endOfObjs (objs + 6)
```
# Object.c
## Object.c
```c
#include <stdio.h>
@@ -159,19 +163,20 @@ OBJECT objs[] = {
};
```
<strong>注意:</strong>要编译此模块,编译器<em>必须</em>支持 Constant folding。这排除了一些更原始的编译器如 [Z88DK](http://en.wikipedia.org/wiki/Z88DK)。
<strong>注意:</strong>要编译此模块,编译器*必须*支持 Constant folding。这排除了一些更原始的编译器如 [Z88DK](http://en.wikipedia.org/wiki/Z88DK)。
以下模块将帮助我们找到与指定名词匹配的对象。
# noun.h
## noun.h
```c
extern OBJECT *getVisible(const char *intention, const char *noun);
```
# 指针?函数?希望你已经掌握这是什么了
::: warning <font size=5>**🤔 指针?函数?希望你已经掌握这是什么了**</font>
:::
# noun.c
## noun.c
```c
#include <stdbool.h>
@@ -227,15 +232,15 @@ OBJECT *getVisible(const char *intention, const char *noun)
}
```
这是另一个辅助程序的函数。它打印存在于特定位置的对象物品NPC的列表。它将用于函数 <em>executeLook</em>,在下一章中,我们将介绍另一个需要它的命令。
这是另一个辅助程序的函数。它打印存在于特定位置的对象物品NPC的列表。它将用于函数 *executeLook*,在下一章中,我们将介绍另一个需要它的命令。
# misc.h
## misc.h
```c
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdio.h>
@@ -251,7 +256,7 @@ int listObjectsAtLocation(OBJECT *location)
//排除玩家在玩家的位置这种蠢东西
{
if (count++ == 0)
//我们需要保证找到一个东西之前他不会打印you see
//我们需要保证找到一个东西之前他不会打印 you see
{
printf("You see:\n");
}
@@ -263,16 +268,16 @@ int listObjectsAtLocation(OBJECT *location)
}
```
<em>location.c</em> 中,命令环<em>顾四周的实现</em>,并根据新的数据结构进行调整。旧的位置数组被删除,变量 <em>locationOfPlayer</em> 也是如此。
*location.c* 中,命令环*顾四周的实现*,并根据新的数据结构进行调整。旧的位置数组被删除,变量 *locationOfPlayer* 也是如此。
# location.h
## location.h
```c
extern void executeLook(const char *noun);
extern void executeGo(const char *noun);
```
# location.c
## location.c
```c
#include <stdio.h>
@@ -297,7 +302,7 @@ void executeLook(const char *noun)
void executeGo(const char *noun)
{
//消除了函数<em>executeGo</em>中的循环,代码更优雅了~
//消除了函数*executeGo*中的循环,代码更优雅了~
OBJECT *obj = getVisible("where you want to go", noun);
if (obj == NULL)
{

View File

@@ -8,19 +8,14 @@
玩家属性不再需要存储在单独的变量中;我们可以使用与任何其他对象相同的数据结构。所以玩家,作为一个对象必须具有以下特点:
- 所处位置(我在哪)
- 所处位置我在哪)
- 玩家可能持有的任何物品的位置。
这使得某些常见操作非常容易实现:
```
<strong> Action </strong> <strong>Typical</strong>
```
<strong> command </strong> <strong>Example</strong>
| 玩家从一个位置移动到另一个位置 | go | player->location = cave; |
|**Action**|**Typical Command**|**Example**|
| ------------------------------ | --------- | ------------------------------------ |
| 玩家从一个位置移动到另一个位置 | go | player->location = cave; |
| 列出某个位置存在的项和参与者 | look | listObjectsAtLocation(cave); |
| 玩家获取物品 | get | silver->location = player; |
| 玩家掉落物品 | drop | silver->location = player->location; |
@@ -29,13 +24,15 @@
| 玩家从演员那里收到物品 | ask | silver->location = player; |
| 列出其他演员的库存 | examine | listObjectsAtLocation(guard); |
你可以尝试去使用这些命令(上面的前两个示例已经在上一章中实现了)。现在,我们将为玩家和非玩家角色介绍一些典型的<strong>物品栏</strong>操作(命令<em>获取</em>、<em>掉落</em>、<em>给予</em>、<em>询问</em>和<em>物品栏</em>)。
你可以尝试去使用这些命令(上面的前两个示例已经在上一章中实现了)。现在,我们将为玩家和非玩家角色介绍一些典型的**物品栏**操作(命令*获取*、*掉落*、*给予*、*询问*和*物品栏*)。
思考题:你能不能尝试自己实现一下上面的命令?
::: warning 🤔 思考题:
你能不能尝试自己实现一下上面的命令?
如果你可以在不参考下面内容的情况下就写出基本内容会有很大收获的
:::
# <strong>parsexec.c</strong>
## parsexec.c
```c
#include <stdbool.h>
@@ -48,7 +45,7 @@ bool parseAndExecute(char *input)
{
char *verb = strtok(input, " \n");
char *noun = strtok(NULL, " \n");
//第二次使用strtok要用NULL传参
//第二次使用 strtok 要用 NULL 传参
if (verb != NULL)
{
if (strcmp(verb, "quit") == 0)
@@ -94,7 +91,7 @@ bool parseAndExecute(char *input)
新命令由以下模块实现。
# <strong>inventory.h</strong>
## inventory.h
```c
extern void executeGet(const char *noun);
@@ -104,7 +101,7 @@ extern void executeGive(const char *noun);
extern void executeInventory(void);
```
# <strong>inventory.c</strong>
## inventory.c
```c
#include <stdio.h>
@@ -163,21 +160,23 @@ void executeInventory(void)
}
```
注意:由于动词名词比较好弄,命令 <em>ask</em> 和 <em>give</em> 只有一个参数item。
注意:由于动词名词比较好弄,命令 *ask**give* 只有一个参数item。
思考题:为什么我们要这样设计?
::: warning 🤔 思考题:
为什么我们要这样设计?
你能否为这些命令多加几个参数?
:::
从本质上讲,<em>get</em>, <em>drop</em>, <em>give</em> and <em>ask 这些命令</em>除了将项目从一个地方移动到另一个地方之外,什么都不做。单个函数 <em>move 对象</em>可以对所有四个命令执行该操作。
从本质上讲,*get*, *drop*, *give* and *ask 这些命令*除了将项目从一个地方移动到另一个地方之外,什么都不做。单个函数 *move 对象*可以对所有四个命令执行该操作。
# move.h
## move.h
```c
extern void moveObject(OBJECT *obj, OBJECT *to);
```
# move.c
## move.c
```c
#include <stdio.h>
@@ -227,18 +226,19 @@ void moveObject(OBJECT *obj, OBJECT *to)
}
```
思考题:识别一些我们拿不了的物品需要考虑什么因素?
::: warning 🤔 思考题:识别一些我们拿不了的物品需要考虑什么因素?
:::
命令“get”使用函数<em>getVisible</em>将名词转换为 object就像命令“go”一样;请参阅上一章。但是对于对玩家(或其他一些参与者)已经持有的对象进行<em>drop</em>, <em>ask</em>, <em>give 等</em>命令时,我们需要稍微不同的东西。我们将在 <em>noun.c</em> 中添加一个函数 <em>getPossession</em>
命令“get”使用函数*getVisible*将名词转换为 object就像命令“go”一样;请参阅上一章。但是对于对玩家(或其他一些参与者)已经持有的对象进行*drop*, *ask*, *give 等*命令时,我们需要稍微不同的东西。我们将在 *noun.c* 中添加一个函数 *getPossession*
# noun.h
## noun.h
```c
extern OBJECT *getVisible(const char *intention, const char *noun);
extern OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun);
```
# noun.c
## noun.c
```c
#include <stdbool.h>
@@ -318,18 +318,18 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
}
```
注意新函数45-75 行) <em>getPossession</em> 是 <em>getObject</em> 的装饰器wrapper )(参见第 52 行),它要么返回匹配的对象,要么返回 NULL如果没有合适的对象与名词匹配
注意新函数45-75 行) *getPossession**getObject* 的装饰器wrapper参见第 52 行),它要么返回匹配的对象,要么返回 NULL如果没有合适的对象与名词匹配
函数 <em>actor 这里</em>用于命令 <em>give</em> 和 <em>ask</em>,但它也可能由其他命令调用。所以我们在<em>misc.c</em>中定义了它。
函数 *actor 这里*用于命令 *give**ask*,但它也可能由其他命令调用。所以我们在*misc.c*中定义了它。
# misc.h
## misc.h
```c
extern OBJECT *actorHere(void);
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdio.h>
@@ -367,9 +367,10 @@ int listObjectsAtLocation(OBJECT *location)
}
```
思考题:上面第四行中的函数 actorHere 返回的指针指向什么?
::: warning 🤔 思考题:上面第四行中的函数 actorHere 返回的指针指向什么?
:::
在第 9 行中,有一个详尽的,硬编码的非玩家角色列表(到目前为止,只有一个:<em>守卫</em>)。
在第 9 行中,有一个详尽的,硬编码的非玩家角色列表(到目前为止,只有一个:*守卫*)。
在第 10 章中,我们将开始使用属性作为区分角色与项目和其他非参与者对象的更优雅方式。

View File

@@ -1,17 +1,17 @@
# 6.绘制地图
作为一个 RPG 游戏怎么能没有地图呢,<em>是时候绘制地图了!</em>
作为一个 RPG 游戏怎么能没有地图呢,*是时候绘制地图了!*
绘制地图的最佳工具始终是:一支铅笔和一张纸。基本地图由<strong>位置</strong>(矩形)组成,由道路(箭头)连接。我们已经在第 3 章中创建了位置,现在我们将开始添加道路。
绘制地图的最佳工具始终是:一支铅笔和一张纸。基本地图由**位置**(矩形)组成,由道路(箭头)连接。我们已经在第 3 章中创建了位置,现在我们将开始添加道路。
在虚拟世界中,“道路”可能是连接两个位置的任何东西:一条路,一扇门,沙漠中。基本上,一段经文具有以下属性:
- 起点(位置)。
- 目标(位置)。
- 叙述性描述,例如“森林小径”。
-<em>go</em> 命令中往哪里走的描述性标记
-*go* 命令中往哪里走的描述性标记
考虑到这些属性,第 4 章中定义的结构对象就非常适合存储道路了。事实上,一个道路与一个项目或 NPC 并没有太大的不同它作为“可见出口”存在于某个位置该位置是起点。它只是与某些命令的行为不同特别是命令“go”应用于道路<em>go</em>将改变玩家的位置。
考虑到这些属性,第 4 章中定义的结构对象就非常适合存储道路了。事实上,一个道路与一个项目或 NPC 并没有太大的不同它作为“可见出口”存在于某个位置该位置是起点。它只是与某些命令的行为不同特别是命令“go”应用于道路*go*将改变玩家的位置。
```c
struct object {
@@ -24,15 +24,16 @@ struct object {
注意:
- 显然,<em>目的地</em>在大多数其他对象物品NPC中都没有使用
- 显然,*目的地*在大多数其他对象物品NPC中都没有使用
- 通道总是朝一个方向运行;要双向连接两个位置我们总是必须创建两个单独的通道。乍一看这似乎很笨拙但它确实给了我们很大的灵活性来完善命令“go”的行为
- 在大地图上,你可能会发现手动创建所有通道很乏味。所以,我强烈建议你使用自定义工具<em>生成</em>地图中重复性更强的部分。这里不会介绍这一点,但您可能会在第 9 章中找到一些灵感,我们将在其中讨论自动胜场。
- 在大地图上,你可能会发现手动创建所有通道很乏味。所以,我强烈建议你使用自定义工具*生成*地图中重复性更强的部分。这里不会介绍这一点,但您可能会在第 9 章中找到一些灵感,我们将在其中讨论自动胜场。
思考题:为什么创建两个通道可以使我们的程序更加灵活?
::: warning 🤔 思考题:为什么创建两个通道可以使我们的程序更加灵活?
:::
接下来我们将展开对象数组
# object.h
## object.h
```c
typedef struct object {
@@ -56,7 +57,7 @@ extern OBJECT objs[];
#define endOfObjs (objs + 8)
```
# object.c
## object.c
```c
#include <stdio.h>
@@ -74,9 +75,9 @@ OBJECT objs[] = {
};
```
我们将在 <em>misc.c</em> 中添加一个小的帮助函数,以确定两个给定位置之间是否存在通道。
我们将在 *misc.c* 中添加一个小的帮助函数,以确定两个给定位置之间是否存在通道。
# misc.h
## misc.h
```c
extern OBJECT *getPassage(OBJECT *from, OBJECT *to);
@@ -84,7 +85,7 @@ extern OBJECT *actorHere(void);
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdio.h>
@@ -138,16 +139,16 @@ int listObjectsAtLocation(OBJECT *location)
}
```
我们将在命令“go”的实现中使用新功能<em>getPassage</em>来确定是否存在可以将玩家带到所需位置的通道。
我们将在命令“go”的实现中使用新功能*getPassage*来确定是否存在可以将玩家带到所需位置的通道。
# location.h
## location.h
```c
extern void executeLook(const char *noun);
extern void executeGo(const char *noun);
```
# location.c
## location.c
```c
#include <stdio.h>
@@ -177,7 +178,7 @@ void executeGo(const char *noun)
// already handled by getVisible
}
else if (getPassage(player->location, obj) != NULL)
//go只会在有地方的时候才会运行起来
//go 只会在有地方的时候才会运行起来
{
printf("OK.\n");
player->location = obj;
@@ -200,16 +201,16 @@ void executeGo(const char *noun)
}
```
我们还将使用新功能<em>getPassage</em>来确定从玩家站立的位置是否可以看到某个位置。未通过通道连接到当前位置的位置不被视为可见。
我们还将使用新功能*getPassage*来确定从玩家站立的位置是否可以看到某个位置。未通过通道连接到当前位置的位置不被视为可见。
# noun.h
## noun.h
```c
extern OBJECT *getVisible(const char *intention, const char *noun);
extern OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun);
```
# noun.c
## noun.c
```c
#include <stdbool.h>
@@ -294,11 +295,12 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
显然,此示例中的地图是微不足道的:只有两个位置,并且它们在两个方向上都连接在一起。第 12 章将增加第三个地点。
思考题:你能否绘制一张更精细的地图,并将其变成对象列表(位置和通道)
::: warning 🤔 思考题:
你能否绘制一张更精细的地图,并将其变成对象列表(位置和通道)
```
注:不用当成任务,自行实验即可
```
注:不用当成任务,自行实验即可
:::
输出样例

View File

@@ -1,23 +1,23 @@
# 7.增大距离
<em>一个典型的冒险包含许多谜题。</em><em>众所周知Infocom</em><em>的冒险很难完成。解决每个难题可能需要数周甚至数月的反复试验。</em>
*一个典型的冒险包含许多谜题。众所周知,[Infocom](https://en.wikipedia.org/wiki/Infocom)的冒险很难完成。解决每个难题可能需要数周甚至数月的反复试验。*
<em>当玩家操纵角色失败后,如果只是返回“你</em><em>不能这么操作</em><em>”来回应玩家</em><em>,会很 nt很没意思</em><em>。</em>
*当玩家操纵角色失败后,如果只是返回“你不能这么操作”来回应玩家,会很 nt很没意思。*
<em>它忽略了</em><em>电脑</em><em>游戏的一个重要方面,而这也是生活本身的一部分:玩家必须从错误中吸取教训。</em>
*它忽略了电脑游戏的一个重要方面,而这也是生活本身的一部分:玩家必须从错误中吸取教训。*
当你的游戏反复输入东西都是,你不能这样做的时候,会显得很无聊的。
<em>冒险游戏至少应该做的是解释为什么玩家的命令无法完成:“你不能这样做,因为......”这有助于使虚拟世界更具说服力,故事更可信,游戏更有趣。</em>
*冒险游戏至少应该做的是解释为什么玩家的命令无法完成:“你不能这样做,因为......”这有助于使虚拟世界更具说服力,故事更可信,游戏更有趣。*
我们已经付出了相当大的努力让游戏解释<strong>为什么</strong>某些命令是无效的。只需看看<em>名词.cinventory.clocation.c</em><em>move.c</em>中的许多<em>printf</em>调用。 但随着游戏变得越来越复杂,这正成为一个相当大的负担。我们需要一种更结构化的方法来检测和处理错误情况。这就是我们在本章中将要讨论的内容。
我们已经付出了相当大的努力让游戏解释**为什么**某些命令是无效的。只需看看*名词.cinventory.clocation.c**move.c*中的许多*printf*调用。但随着游戏变得越来越复杂,这正成为一个相当大的负担。我们需要一种更结构化的方法来检测和处理错误情况。这就是我们在本章中将要讨论的内容。
大多数命令对一个或多个对象进行操作,例如:
- 玩家拿起一件物品,然后把它交给另一个 NPC。
- 玩家沿着一条通道到另一个位置。
首先要检查的(在[解析器](http://en.wikipedia.org/wiki/Parsing)捕获检测是否会有明显[拼写错误](http://en.wikipedia.org/wiki/Typographical_error)之后)是这些对象<strong>是否存在</strong>;
首先要检查的(在[解析器](http://en.wikipedia.org/wiki/Parsing)捕获检测是否会有明显[拼写错误](http://en.wikipedia.org/wiki/Typographical_error)之后)是这些对象**是否存在**;
失败应该导致类似“这里没有...“或”你看不到任何东西...”等文字出现。在本章中,我们将构建一个通用函数,每个命令都可以使用它来找出玩家是否在可及的范围内。
@@ -38,7 +38,7 @@
| distHereContained | 一个物体NPC 或“容器”)存在于玩家的位置,正在拿着另一个物体 | object->location != NULL &&<br/>object->location->location == player->location |
| distOverthere | 对象是附近的位置 | getPassage(player->location, object) != NULL |
第一种情况对象是玩家可能看起来微不足道但它仍然很重要。例如命令“examine yourself”<em>不应该</em>返回“这里没有你自己”。
第一种情况对象是玩家可能看起来微不足道但它仍然很重要。例如命令“examine yourself”*不应该*返回“这里没有你自己”。
我试图遵循一个逻辑顺序:附近的事物最高优先级,随后优先级会变低。
@@ -48,7 +48,7 @@
请注意,我们有七种不同的“这里”案例,但只有一种是“不在这里”。这是因为通常,游戏只需要提供有关玩家可以感知的事物的信息。如果它不在这里,那么就没什么可说的了。
在最左边的列中,我们为每个案例提出了一个符号名称。我们将在名为 <strong>DISTANCE</strong> 的[枚举](http://en.wikipedia.org/wiki/Enumerated_type)中收集这些名称。
在最左边的列中,我们为每个案例提出了一个符号名称。我们将在名为 **DISTANCE** 的[枚举](http://en.wikipedia.org/wiki/Enumerated_type)中收集这些名称。
```c
typedef enum {
@@ -64,7 +64,8 @@ typedef enum {
} DISTANCE;
```
typedef 以及枚举类 enum 之前有接触过吗?没有接触过的话就去学习一下吧。
::: warning 💡 typedef 以及枚举类 enum 之前有接触过吗?没有接触过的话就去学习一下吧。
:::
在最右边的列中,我们为每个情况提出了一个满足条件。通过一些重新洗牌,我们可以很容易地将其转换为计算对象“距离”的函数(从玩家的角度来看):
@@ -84,11 +85,13 @@ DISTANCE getDistance(OBJECT *from, OBJECT *to)
}
```
思考题:你是否有其他方法实现这个功能?
::: warning 🤔 思考题:
你是否有其他方法实现这个功能?
注:自行实验即可
:::
就这样!我们可以调用此函数并对其返回值进行比较。例如,我们在 noun<em>.c</em>中有以下代码:
就这样!我们可以调用此函数并对其返回值进行比较。例如,我们在 noun*.c*中有以下代码:
```c
else if (!(obj == player ||
@@ -110,7 +113,7 @@ else if (!(getDistance(player, obj) == distSelf ||
getDistance(player, obj) == distHere ||
getDistance(player, obj) == distOverthere ||
getDistance(player, obj) == distHeldContained ||
getDistance(player, obj) == distHereContained)
getDistance(player, obj) == distHereContained))
```
这可以简化为:
@@ -119,13 +122,14 @@ else if (!(getDistance(player, obj) == distSelf ||
else if (getDistance(player, obj) >= distNotHere)
```
尝试理解一下这样做的意义
::: warning 🤔 尝试理解一下这样做的意义
:::
这只是一个例子,让你对这个概念有所了解;您将在下面找到<em>noun.c</em>的实际实现,看起来略有不同。
这只是一个例子,让你对这个概念有所了解;您将在下面找到*noun.c*的实际实现,看起来略有不同。
是时候把事情落实到位了。枚举 <em>DISTANCE</em> 和函数 <em>getDistance</em> 的定义被添加到 <em>misc.h</em> 和 <em>misc.c</em> 中,因为我们将在多个模块中使用它们。
是时候把事情落实到位了。枚举 *DISTANCE* 和函数 *getDistance* 的定义被添加到 *misc.h**misc.c* 中,因为我们将在多个模块中使用它们。
# misc.h
## misc.h
```c
typedef enum {
@@ -150,7 +154,7 @@ extern OBJECT *actorHere(void);
extern int listObjectsAtLocation(OBJECT *location);
```
# misc.c
## misc.c
```c
#include <stdbool.h>
@@ -226,16 +230,16 @@ int listObjectsAtLocation(OBJECT *location)
注意isHolding 这个函数之后我们将在各个地方使用
# location.h
## location.h
```c
extern void executeLook(const char *noun);
extern void executeGo(const char *noun);
```
在函数 <em>executeGo</em> 中,我们可以用检查距离来替换大多数 <em>if</em> 条件。
在函数 *executeGo* 中,我们可以用检查距离来替换大多数 *if* 条件。
# location.c
## location.c
```c
#include <stdbool.h>
@@ -290,11 +294,12 @@ void executeGo(const char *noun)
}
```
思考题:你能否为 switch 函数增加更多 case 来完善判断条件?
::: warning 🤔 思考题:你能否为 switch 函数增加更多 case 来完善判断条件?
:::
函数 <em>executeGet</em> 也是如此。
函数 *executeGet* 也是如此。
# <strong>inventory.h</strong>
## **inventory.h**
```c
extern void executeGet(const char *noun);
@@ -304,7 +309,7 @@ extern void executeGive(const char *noun);
extern void executeInventory(void);
```
# <strong>inventory.c</strong>
## **inventory.c**
```c
#include <stdbool.h>
@@ -367,16 +372,16 @@ void executeInventory(void)
}
```
最后,我们将调整 noun<em>.c</em>中的约束。我们正在向函数<em>getObject</em>添加两个参数,以便找到特定名词的匹配项,同时忽略任何被认为不存在的对象。这将在下一章中得到真正的回报,我们将在下一章中介绍具有相同标签的不同对象。
最后,我们将调整 noun*.c*中的约束。我们正在向函数*getObject*添加两个参数,以便找到特定名词的匹配项,同时忽略任何被认为不存在的对象。这将在下一章中得到真正的回报,我们将在下一章中介绍具有相同标签的不同对象。
# noun.h
## noun.h
```c
extern OBJECT *getVisibleconst char *intention const char *noun;
extern OBJECT *getPossessionOBJECT *from const char *verb const char *noun;
```
# noun.c
## noun.c
```c
#include <stdbool.h>
@@ -455,9 +460,10 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
}
```
思考题:你能理解什么时候加 const什么时候不用吗
::: warning 🤔 思考题:你能理解什么时候加 const什么时候不用吗
:::
在本章中,<em>距离</em>的概念主要用于在游戏可以给用户的不同响应之间进行选择。但是,距离的好处并不局限于<strong>输出</strong>端;它可以同样很好地用于在<strong>输入</strong>端进行改进。在下一章中,我们将使用距离来提高对用户输入的名词的识别。
在本章中,*距离*的概念主要用于在游戏可以给用户的不同响应之间进行选择。但是,距离的好处并不局限于**输出**端;它可以同样很好地用于在**输入**端进行改进。在下一章中,我们将使用距离来提高对用户输入的名词的识别。
输出样例

View File

@@ -1,13 +1,14 @@
# 8.移动方向
<em>传统的文本冒险使用</em><em>指南针方向</em><em>进行导航。</em>
*传统的文本冒险使用[指南针方向](https://en.wikipedia.org/wiki/Cardinal_direction)进行导航。*
例如,我们在第 6 章中绘制的地图上,玩家可能想<strong>向东</strong>移动,从田野移动到洞穴。我们可以通过给连接<strong>Cave</strong>的通道标上“east”来实现这一点。但是我们首先需要解决两个问题。
例如,我们在第 6 章中绘制的地图上,玩家可能想**向东**移动,从田野移动到洞穴。我们可以通过给连接**Cave**的通道标上“east”来实现这一点。但是我们首先需要解决两个问题。
1. 我们可能仍然想把这段通道称为“entrance”和“east”。但现在一个对象只能有一个标签。
2. 在更大的地图上具有更多的位置和道路标签“east”将被定义多次。到目前为止标签在我们的游戏中是全球独一无二的没有重复项。
思考题:你能否想出解决办法?
::: warning 🤔 思考题:你能否想出解决办法?
:::
这些问题同样适用于其他对象,而不仅仅是通道。
@@ -17,11 +18,11 @@
这立即将我们带到了解析器的第三个问题:
1. 一个标签只能是一个单词;“ sliver coin”这是俩单词他不接受啊
1. 一个标签只能是一个单词;“sliver coin”这是俩单词他不接受啊
所有三个问题都将在本章中解决,从问题#1 开始。它通过为每个对象提供一个标签列表来解决,而不仅仅是一个标签。
# object.h
## object.h
```c
typedef struct object {
@@ -47,7 +48,7 @@ extern OBJECT objs[];
#define endOfObjs (objs + 10)
```
# object.c
## object.c
```c
#include <stdio.h>
@@ -63,7 +64,7 @@ static const char *tags6[] = {"east", "entrance", NULL};
static const char *tags7[] = {"west", "exit", NULL};
static const char *tags8[] = {"west", "north", "south", "forest", NULL};
static const char *tags9[] = {"east", "north", "south", "rock", NULL};
//我们不固定标签长度在结束的时候用NULL来标记
//我们不固定标签长度,在结束的时候用 NULL 来标记
OBJECT objs[] = {
{"an open field" , tags0, NULL , NULL },
{"a little cave" , tags1, NULL , NULL },
@@ -75,22 +76,22 @@ OBJECT objs[] = {
{"an exit to the west" , tags7, cave , field },
{"dense forest all around" , tags8, field, NULL },
{"solid rock all around" , tags9, cave , NULL }
//我们用NULL来阻绝进入一个你不知道的地方
//我们用 NULL 来阻绝进入一个你不知道的地方
};
```
当然,要让这个改动生效,我们还需要调整<em>noun.c</em>中的<em>objectHasTag</em>函数。
当然,要让这个改动生效,我们还需要调整*noun.c*中的*objectHasTag*函数。
<em>同时,我们将让函数 getVisible</em>和<em>getPossession</em> 告知玩家他必须更具体的选择你到底是银币还是金币 ,而不是随机选择任何一个对象。
*同时,我们将让函数 getVisible*和*getPossession* 告知玩家他必须更具体的选择你到底是银币还是金币,而不是随机选择任何一个对象。
# noun.h
## noun.h
```c
extern OBJECT *getVisible(const char *intention, const char *noun);
extern OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun);
```
# <strong>noun.c</strong>
## **noun.c**
```c
#include <stdbool.h>
@@ -107,7 +108,7 @@ static bool objectHasTag(OBJECT *obj, const char *noun)
for (tag = obj->tags; *tag != NULL; tag++)
{
if (strcmp(*tag, noun) == 0) return true;
}//扫描对象的tag列表
}//扫描对象的 tag 列表
}
return false;
}
@@ -187,9 +188,9 @@ OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
}
```
问题 #3 可以通过从函数<em>parseAndExecute</em>中删除一个 [空格](http://en.wikipedia.org/wiki/Space_(punctuation))字符来解决(下面的第 10 行)。这个解决方案远非完美('silver' 和 'coin' 之间的双空格是咩的),但直到我们在第 13 章中让自己成为一个更好的解析器之前。
问题 #3 可以通过从函数*parseAndExecute*中删除一个 [空格](http://en.wikipedia.org/wiki/Space_(punctuation))字符来解决(下面的第 10 行)。这个解决方案远非完美('silver' 和 'coin' 之间的双空格是咩的),但直到我们在第 13 章中让自己成为一个更好的解析器之前。
# parsexec.c
## parsexec.c
```c
#include <stdbool.h>
@@ -245,8 +246,9 @@ bool parseAndExecute(char *input)
}
```
模块<em>main.c</em>、<em>inventory.c</em>、<em>location.c</em>、<em>move.c</em> 和<em>misc.c</em>保持不变
模块*main.c*、*inventory.c*、*location.c*、*move.c* 和*misc.c*保持不变
现在对象数组 ( <em>object.c</em> ) 开始在多个维度上增长(特别是在引入多个标签的情况下),我们需要一种使其更易于维护的方法。
现在对象数组 ( *object.c* ) 开始在多个维度上增长(特别是在引入多个标签的情况下),我们需要一种使其更易于维护的方法。
猜猜看该怎么办?
::: warning 🤔 猜猜看该怎么办?
:::

View File

@@ -1,10 +1,10 @@
# 9.练习:生成代码
# 9.练习生成代码
*到目前为止我们的冒险游戏有10个对象。每个对象由有5 个属性组成。一个真正的文本冒险可能有数百个甚至数千个对象,并且每个对象的属性数量也可能增加(请参阅下一章)。在目前的形式下,维护如此庞大的对象和属性列表将很困难。*
*到目前为止,我们的冒险游戏有 10 个对象。每个对象由有 5 个属性组成。一个真正的文本冒险可能有数百个甚至数千个对象,并且每个对象的属性数量也可能增加(请参阅下一章)。在目前的形式下,维护如此庞大的对象和属性列表将很困难。*
例如,当我们在添加对象 *wallField**wallCave* 时,我们必须在三个不同的位置执行此操作:一次在 *object.h* 中(作为*#define*),两次在 *object.c* 中(数组 *objs* 中的一个元素,以及一个单独的标签数组)。这显然十分笨拙并且容易出错。
例如,当我们在添加对象 *wallField**wallCave* 时,我们必须在三个不同的位置执行此操作:一次在 *object.h* 中(作为<em>#define</em>),两次在 *object.c* 中(数组 *objs* 中的一个元素,以及一个单独的标签数组)。这显然十分笨拙并且容易出错。
我们将不再手工维护object. hobject. c而是从更适合我们需要的单一源开始生成文件。这个新的源文件可以用你喜欢的任何语言( 典型的是某些特定领域的语言 )只要你有工具把它转换回C。下面是一个简单的例子考虑下列布局来组织我们的对象
我们将不再手工维护 object. hobject. c而是从更适合我们需要的单一源开始生成文件。这个新的源文件可以用你喜欢的任何语言 ( 典型的是某些特定领域的语言 ),只要你有工具把它转换回 C。下面是一个简单的例子考虑下列布局来组织我们的对象
```txt
/* Raw C code (declarations) */
@@ -21,7 +21,7 @@
根据到目前为止收集的对象,我们可以构造以下源文件。文件名并不重要;我只是简单地将其命名为*object.txt*,以明确它与*object.h*和*object.c*相关。
# object.txt
## object.txt
```txt
#include <stdio.h>
@@ -87,4 +87,5 @@ extern OBJECT objs[];
location cave
```
思考题:你能否自己用C来实现这段伪代码?
::: warning 🤔 思考题:你能否自己用 C 来实现这段伪代码?
:::

View File

@@ -1,10 +1,10 @@
# 阶段二文字冒险cool
# 前言
## 前言
本来打算让各位做下面的任务来进行进一步的学习的,但是想了想,实在是,<strong>太无聊啦</strong>
本来打算让各位做下面的任务来进行进一步的学习的,但是想了想,实在是,**太无聊啦**
又想让你们来做一个管理系统,但是又想到你们可能会进行无数个管理系统,<strong>这也太无聊啦</strong>
又想让你们来做一个管理系统,但是又想到你们可能会进行无数个管理系统,**这也太无聊啦**
因此呢,我打算带大家玩一个文字冒险游戏![源头取自这里](https://github.com/helderman/htpataic),如果你想自己体验全流程的话可以试试玩哦!
@@ -20,24 +20,24 @@
当然,如果你选择跳过,也不会对 python 开发那里造成非常大的影响但是你会错失一个非常宝贵的学习机会。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnustZBhjMu8FPN0Kxi4Mwvf.jpg)
![](https://cdn.xyxsw.site/boxcnustZBhjMu8FPN0Kxi4Mwvf.jpg)
在 1980 年代, [文字冒险](http://en.wikipedia.org/wiki/Text_adventure) 是一种受人尊敬的电脑游戏类型。但是时代已经变了,在 21 世纪,它们与 带有 3D 引擎的现代 [MMORPG 相比显得苍白无力。](http://en.wikipedia.org/wiki/Mmorpg)书籍在电影的兴起中幸存下来,而基于文本的游戏很快就输掉了与图形游戏的战斗。“互动小说”由一个活跃的社区保持活力,但它的商业价值早已不复存在。
# 系统调试的黄金法则KISS 原则
## 系统调试的黄金法则KISS 原则
这里的 `KISS``Keep It Simple, Stupid` 的缩写, 它的中文翻译是: 不要在一开始追求绝对的完美.
这里的 `KISS``Keep It Simple, Stupid` 的缩写它的中文翻译是不要在一开始追求绝对的完美
随着以后代码量会越来越多, 各个模块之间的交互也越来越复杂, 工程的维护变得越来越困难, 一个很弱智的 bug 可能需要调好几天.
随着以后代码量会越来越多各个模块之间的交互也越来越复杂工程的维护变得越来越困难一个很弱智的 bug 可能需要调好几天
在这种情况下, 系统能跑起来才是王道, 跑不起来什么都是浮云, 追求面面俱到只会增加代码维护的难度.
在这种情况下系统能跑起来才是王道跑不起来什么都是浮云追求面面俱到只会增加代码维护的难度
唯一可以把你从 bug 的混沌中拯救出来的就是 KISS 法则, 它的宗旨是<strong>从易到难, 逐步推进</strong>, 一次只做一件事, 少做无关的事.
唯一可以把你从 bug 的混沌中拯救出来的就是 KISS 法则它的宗旨是**从易到难逐步推进**, 一次只做一件事少做无关的事
如果你不知道这是什么意思, 我们以可能发生的 `str` 成员缓冲区溢出问题来作为例子. KISS 法则告诉你, 你应该使用 `assert(0)`, 就算不"得体"地处理上述问题, 仍然不会影响表达式求值的核心功能的正确性.
如果你不知道这是什么意思我们以可能发生的 `str` 成员缓冲区溢出问题来作为例子KISS 法则告诉你你应该使用 `assert(0)`, 就算不"得体"地处理上述问题仍然不会影响表达式求值的核心功能的正确性
如果你还记得调试公理, 你会发现两者之间是有联系的: 调试公理第二点告诉你, 未测试代码永远是错的. 与其一下子写那么多"错误"的代码, 倒不如使用 `assert(0)` 来有效帮助你减少这些"错误".
如果你还记得调试公理你会发现两者之间是有联系的调试公理第二点告诉你未测试代码永远是错的与其一下子写那么多"错误"的代码倒不如使用 `assert(0)` 来有效帮助你减少这些"错误".
如果把 KISS 法则放在软件工程领域来解释, 它强调的就是多做[单元测试](http://en.wikipedia.org/wiki/Unit_testing): 写一个函数, 对它进行测试, 正确之后再写下一个函数, 再对它进行测试... 一种好的测试方式是使用 assertion 进行验证,
如果把 KISS 法则放在软件工程领域来解释它强调的就是多做[单元测试](http://en.wikipedia.org/wiki/Unit_testing): 写一个函数对它进行测试正确之后再写下一个函数再对它进行测试... 一种好的测试方式是使用 assertion 进行验证
KISS 法则不但广泛用在计算机领域, 就连其它很多领域也视其为黄金法则, [这里](http://blog.sciencenet.cn/blog-414166-562616.html)有一篇文章举出了很多的例子, 我们强烈建议你阅读它, 体会 KISS 法则的重要性.
KISS 法则不但广泛用在计算机领域就连其它很多领域也视其为黄金法则[这里](http://blog.sciencenet.cn/blog-414166-562616.html)有一篇文章举出了很多的例子我们强烈建议你阅读它体会 KISS 法则的重要性

View File

@@ -1,6 +1,6 @@
# 调试理论
# 调试公理
::: warning 🌲 调试公理
- The machine is always right. (机器永远是对的)
@@ -9,32 +9,34 @@
- Corollary: Mistakes are likely to appear in the "must-be-correct" code.
这两条公理的意思是: 抱怨是没有用的, 接受代码有 bug 的现实, 耐心调试.
这两条公理的意思是抱怨是没有用的接受代码有 bug 的现实耐心调试.
:::
# 如何调试
::: warning 😋 如何调试
- 不要使用"目光调试法", 要思考如何用正确的工具和方法帮助调试
- 程序设计课上盯着几十行的程序, 你或许还能在大脑中像 NEMU 那样模拟程序的执行过程; 但程序规模大了之后, 很快你就会放弃的: 你的大脑不可能模拟得了一个巨大的状态机
- 我们学习计算机是为了学习计算机的工作原理, 而不是学习如何像计算机那样机械地工作
- 使用 `assert()` 设置检查点, 拦截非预期情况
- 程序设计课上盯着几十行的程序你或许还能在大脑中像 NEMU 那样模拟程序的执行过程; 但程序规模大了之后很快你就会放弃的你的大脑不可能模拟得了一个巨大的状态机
- 我们学习计算机是为了学习计算机的工作原理而不是学习如何像计算机那样机械地工作
- 使用 `assert()` 设置检查点拦截非预期情况
- 例如 `assert(p != NULL)` 就可以拦截由空指针解引用引起的段错误
- 结合对程序执行行为的理解, 使用 `printf()` 查看程序执行的情况(注意字符串要换行)
- 结合对程序执行行为的理解使用 `printf()` 查看程序执行的情况 (注意字符串要换行)
- `printf()` 输出任意信息可以检查代码可达性: 输出了相应信息, 当且仅当相应的代码块被执行
- `printf()` 输出变量的值, 可以检查其变化过程与原因
- `printf()` 输出任意信息可以检查代码可达性输出了相应信息当且仅当相应的代码块被执行
- `printf()` 输出变量的值可以检查其变化过程与原因
- 使用 GDB 观察程序的任意状态和行为
- 打印变量, 断点, 监视点, 函数调用栈...
- 打印变量,断点,监视点函数调用栈...
:::
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnaqLMfwqNMTcYEPuF3vFjqg.png)
![](https://cdn.xyxsw.site/boxcnaqLMfwqNMTcYEPuF3vFjqg.png)
# 调试理论
## 什么是调试理论
如果我们能判定任意程序状态的正确性,那么给定一个 failure我们可以通过二分查找定位到第一个 error 的状态,此时的代码就是 fault (bug)。
# 正确的方法:理解程序的执行过程,弄清楚到底为何导致了 bug
## 正确的方法:理解程序的执行过程,弄清楚到底为何导致了 bug
- `ssh`:使用 `-v` 选项检查日志
- `gcc`:使用 `-v` 选项打印各种过程
@@ -44,22 +46,22 @@
各个工具普遍提供调试功能,帮助用户/开发者了解程序的行为
# 错误概念
## 错误概念
我们来简单梳理一下段错误发生的原因. 首先, 机器永远是对的. 如果程序出了错, 先怀疑自己的代码有 bug . 比如由于你的疏忽, 你编写了 `if (p = NULL)` 这样的代码. 但执行到这行代码的时候, 也只是 `p` 被赋值成 `NULL`, 程序还会往下执行. 然而等到将来对 `p` 进行了解引用的时候, 才会触发段错误, 程序彻底崩溃.
我们来简单梳理一下段错误发生的原因。首先,机器永远是对的如果程序出了错先怀疑自己的代码有 bug . 比如由于你的疏忽你编写了 `if (p = NULL)` 这样的代码但执行到这行代码的时候也只是 `p` 被赋值成 `NULL`, 程序还会往下执行然而等到将来对 `p` 进行了解引用的时候才会触发段错误程序彻底崩溃
我们可以从上面的这个例子中抽象出一些软件工程相关的概念:
我们可以从上面的这个例子中抽象出一些软件工程相关的概念
- Fault: 实现错误的代码, 例如 `if (p = NULL)`
- Error: 程序执行时不符合预期的状态, 例如 `p` 被错误地赋值成 `NULL`
- Failure: 能直接观测到的错误, 例如程序触发了段错误
- Fault: 实现错误的代码例如 `if (p = NULL)`
- Error: 程序执行时不符合预期的状态例如 `p` 被错误地赋值成 `NULL`
- Failure: 能直接观测到的错误例如程序触发了段错误
调试其实就是从观测到的 failure 一步一步回溯寻找 fault 的过程, 找到了 fault 之后, 我们就很快知道应该如何修改错误的代码了. 但从上面的例子也可以看出, 调试之所以不容易, 恰恰是因为:
调试其实就是从观测到的 failure 一步一步回溯寻找 fault 的过程找到了 fault 之后我们就很快知道应该如何修改错误的代码了但从上面的例子也可以看出调试之所以不容易恰恰是因为
- fault 不一定马上触发 error
- 触发了 error 也不一定马上转变成可观测的 failure
- error 会像滚雪球一般越积越多, 当我们观测到 failure 的时候, 其实已经距离 fault 非常遥远了
- error 会像滚雪球一般越积越多当我们观测到 failure 的时候其实已经距离 fault 非常遥远了
理解了这些原因之后, 我们就可以制定相应的策略了:
理解了这些原因之后我们就可以制定相应的策略了
- 尽可能把 fault 转变成 error. 这其实就是测试做的事情, 所以我们在上一节中加入了表达式生成器的内容, 来帮助大家进行测试, 后面的实验内容也会提供丰富的测试用例. 但并不是有了测试用例就能把所有 fault 都转变成 error 了, 因为这取决于测试的覆盖度. 要设计出一套全覆盖的测试并不是一件简单的事情, 越是复杂的系统, 全覆盖的测试就越难设计. 但是, 如何提高测试的覆盖度, 是学术界一直以来都在关注的问题.
- 尽可能把 fault 转变成 error. 这其实就是测试做的事情所以我们在上一节中加入了表达式生成器的内容来帮助大家进行测试后面的实验内容也会提供丰富的测试用例但并不是有了测试用例就能把所有 fault 都转变成 error 了因为这取决于测试的覆盖度要设计出一套全覆盖的测试并不是一件简单的事情越是复杂的系统全覆盖的测试就越难设计。但是,如何提高测试的覆盖度是学术界一直以来都在关注的问题

View File

@@ -2,59 +2,63 @@
请在开始进行 C 语言编程之后查阅使用
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnHXggg6eLy86vFmb4shOksh.png)
![](https://cdn.xyxsw.site/boxcnHXggg6eLy86vFmb4shOksh.png)
# GDB 是什么?
## GDB 是什么?
调试器,简单来说就是当你代码跑不通时候修正错误用的
[GDB's Mascot?](https://sourceware.org/gdb/mascot/)
可搭配插件 gef pwndbg pwngdb peda
# 基本操作
## 基本操作
### <strong>GDB 使用表</strong>
[GDB 快速入门教程](https://www.bilibili.com/video/BV1EK411g7Li/)
<em>run r</em>运行程序
### **GDB 使用表**
<em>b</em>打断点,可以在函数和位置打断点
`run (r)`运行程序
<em>info b</em>查看打断点的位置
`b`打断点,可以在函数和位置打断点
<em>n</em>下一步,跳过函数的
`info b`查看打断点的位置
<em>list</em>查看源代码
`n`下一步,跳过函数的
<em>-p</em>走 PID 路线
`list`查看源代码
edit [file:]function 看现在停下的函数位置
`-p`走 PID 路线
step 进入任何函数
`edit [file:]function` 看现在停下的函数位置
<em>p</em>打印变量
`step` 进入任何函数
<em>shell</em>输入命令
`p`打印变量
<em>set logging on</em>记录日志
`shell`输入命令
<em>watchpoint</em>观察变量是否变化的观察点
`set logging on`记录日志
<em>watch</em>设置观察点位置watch*(地址)
`watchpoint`观察变量是否变化的观察点
<em>layout split</em>开启 TUI 模式
`watch`设置观察点位置watch*(地址)
<em>whatis</em>查看变量类型
`layout split`开启 TUI 模式
<em>ptype</em>查看详细信息
`whatis`查看变量类型
#### <strong>TUI</strong>
`ptype`查看详细信息
<em>ctrl +x +a</em>开启
#### **TUI**
<em>ctrl</em>+<em>p</em>+<em>n</em>往前
`ctrl + x + a`开启
<em>ctrl</em> +<em>l</em>重新整理页面
`ctrl + p + n`往前
# 官方手册
`ctrl + l`重新整理页面
## 官方手册
[GDB User Manual](https://sourceware.org/gdb/current/onlinedocs/gdb)

View File

@@ -1,6 +1,6 @@
# C 的历史问题undefined behavior
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnIdOChXQUGMvnxWcB7uTWLh.png)
![](https://cdn.xyxsw.site/boxcnIdOChXQUGMvnxWcB7uTWLh.png)
简写为 UB
@@ -22,7 +22,7 @@ int main(int argc, char **argv) {
}
```
讓我們看看不同編譯器的 Debug 模式下行的
让我们看看不同编译器的 Debug 模式下行的
Visual C++ 6.0
@@ -36,7 +36,7 @@ MinGW(GCC)
> The answer : 25
們試試看在 Release 下行的
们试试看在 Release 下行的
Visual C++ 6.0
@@ -50,9 +50,9 @@ MinGW(GCC)
> The answer : 25
C 言最初為了開發 UNIX 和系統軟體而生,本是低的程式語言,
C 言最初为了开发 UNIX 和系统软体而生,本是低的程式语言
語言規範層級存在 UB可允許編譯器引入更多最佳化。比方 `X * 2 / 2` 在沒有 overflow 生的時候,可最佳化 `X`
语言规范层级存在 UB可允许编译器引入更多最佳化。比方 `X * 2 / 2` 在沒有 overflow 生的時候,可最佳化 `X`
而且值得注意的是,在你的程序初始化之前,栈里面塞的一堆东西也是 UB。
@@ -64,4 +64,4 @@ C 語言最初為了開發 UNIX 和系統軟體而生,本質是低階的程式
[万恶的未定义行为 | 程式设计 遇上 小提琴](https://blog.ez2learn.com/2008/09/27/evil-undefined-behavior/)
<del>关键是,老师喜欢出题刁难你啊!真烦啊!</del>
<del>关键是,老师喜欢出题刁难你啊真烦啊!</del>

View File

@@ -1,16 +1,16 @@
# C 编译器干了什么
# 以 gcc 为例
## 以 gcc 为例
1、预处理,生成 .i 的文件[预处理器 cpp]
1、预处理生成 .i 的文件[预处理器 cpp]
2、将预处理后的文件转换成汇编语言, 生成文件 .s [编译器 egcs]
2、将预处理后的文件转换成汇编语言生成文件 .s [编译器 egcs]
3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器 as]
3、有汇编变为目标代码 (机器代码) 生成 .o 的文件[汇编器 as]
4、连接目标代码, 生成可执行程序 [链接器 ld]
4、连接目标代码生成可执行程序 [链接器 ld]
# 有啥用
## 有啥用
有一天你发现,某一段 C 语言只有几行,但是用了大量的魔法宏定义以及魔法操作以及神奇的元编程。
@@ -18,10 +18,10 @@
如果有一天你要学习汇编语言,或者说出现了在代码中看不出的 bug你可能需要翻译成.s 文件
# 了解更多
## 了解更多
当然不止如此,编译器还承担了优化的过程,有时候同一份代码,经过 O1 和 O2 不同优化可能最后代码都不一样。
推荐阅读
[http://www.ruanyifeng.com/blog/2014/11/compiler.html](http://www.ruanyifeng.com/blog/2014/11/compiler.html)
[编译器的工作过程](http://www.ruanyifeng.com/blog/2014/11/compiler.html)

View File

@@ -1,6 +1,6 @@
# Inline Assembly 与链接加载
# Inline Assembly
## Inline Assembly
可以在 C 代码里嵌入汇编语言的骚操作。毕竟编译器本身也就是个复制,翻译,,粘贴的过程。
@@ -14,27 +14,27 @@ C 艹可能没那么容易了····比如说虚函数调用,那你就不太
当然这里可以参考 c inline Asm 的教程 但是已经脱离了本文的主题了
这里给指条路 [https://dmalcolm.fedorapeople.org/gcc/2015-08-31/rst-experiment/how-to-use-inline-assembly-language-in-c-code.html](https://dmalcolm.fedorapeople.org/gcc/2015-08-31/rst-experiment/how-to-use-inline-assembly-language-in-c-code.html)
这里给指条路 [How to Use Inline Assembly Language in C Code](https://dmalcolm.fedorapeople.org/gcc/2015-08-31/rst-experiment/how-to-use-inline-assembly-language-in-c-code.html)
> 诸如 Go 的高级语言 也可以通过 inline C 来 内链汇编
你可以写任何一个指令,他完全不会检查 也不会优化 编译器默认你知道你在干什么。
然后 C 编译器就会将这部分代码 <strong>原封不动地 </strong>拷贝进你的二进制代码当中
然后 C 编译器就会将这部分代码 **原封不动地**拷贝进你的二进制代码当中
当然,你可以通过 RTFM 来将 C 语言的变量塞到汇编中处理。
在 Windows 平台下 VS 没有 Code 可以以 `__asm {}` 代码块来进行实验 但是注意 只能在 x86 模式下使用 x64 不支持 可以参考 [https://docs.microsoft.com/zh-tw/cpp/assembler/inline/asm?view=msvc-170](https://docs.microsoft.com/zh-tw/cpp/assembler/inline/asm?view=msvc-170)
在 Windows 平台下 VS 没有 Code 可以以 `__asm {}` 代码块来进行实验 但是注意 只能在 x86 模式下使用 x64 不支持 可以参考 [__asm](https://docs.microsoft.com/zh-tw/cpp/assembler/inline/asm?view=msvc-170)
以上两种平台的方案都其实本质是编译器特殊宏 并不包括在 C 的标准内 所以要针对不同的编译器 寻找对应的文档
# 静态链接
## 静态链接
当你使用 GCC 生成可执行文件./a.out 时,到底发生了什么?
为什么就可以直接执行呢?当你问及这个问题时,那么就大有一番探索的空间了
# 链接器
## 链接器
链接器的功能:将一个可执行程序所需的目标文件和库最终整合在一起。
@@ -42,15 +42,13 @@ C 艹可能没那么容易了····比如说虚函数调用,那你就不太
这个就是帮你和外部库连接起来的重要部分。
一个程序包含三个段:.text 、.data 和 .bss 段。
一个程序包含三个段:.text、.data 和 .bss 段。
```
而各目标文件和库都包含这三段所以ld 链接器的功能就是将各个目标文件和库的三段合并在一起。
当然,链接器所完成的链接工作并非只是简单地将各个目标文件和库的三段内存堆砌在一起,而是还要完成 “重定位” 的工作。
```
当然,链接器所完成的链接工作并非只是简单地将各个目标文件和库的三段内存堆砌在一起,而是还要完成“重定位”的工作。
## 查看二进制文件的工具
### 查看二进制文件的工具
使用 objdump 查看 data 节的 xy
@@ -60,7 +58,7 @@ C 艹可能没那么容易了····比如说虚函数调用,那你就不太
使用 IDA BinaryNInja 一类反汇编工具
# 动态链接
## 动态链接
静态链接一次用那么多,实在是太大太大了
@@ -74,7 +72,7 @@ Linux 下一般是 .so 如果你看到了 .a 那个一般是 archive 的缩写
使用动态链接的好处在于 可以热加载和热更新
# 共享连接的加载
## 共享连接的加载
使用 ldd 来查看 a.out 就可以查看动态链接库

View File

@@ -6,7 +6,7 @@
值得一提的是,我不会在本教程讲授过于基础的概念,但是会贴出你可能需要学习的内容。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnAnXUHDqsMYVrDlBfFunoVf.png)
![](https://cdn.xyxsw.site/boxcnAnXUHDqsMYVrDlBfFunoVf.png)
同时我要说的是C 语言为了适配多种多样的硬件以及各式各样的操作,他对非常多的 undefined 操作不做太多限制,也就是说你可能会出现各种各样的问题,<del>甚至把你电脑炸了</del>

View File

@@ -2,13 +2,15 @@
引自 nju-ics-pa
## <strong>光玉</strong>
## 光玉
想象一下你正在玩 Flappy Bird ,你今晚的目标是拿到 100 分,不然就不睡觉。 经过千辛万苦,你拿到了 99 分,就要看到成功的曙光的时候,你竟然失手了!你悲痛欲绝,滴血的心在呼喊着,“为什么上天要这样折磨我?为什么不让我存档?”
想象一下你正在玩 Flappy Bird你今晚的目标是拿到 100 分,不然就不睡觉。经过千辛万苦,你拿到了 99 分,就要看到成功的曙光的时候,你竟然失手了!你悲痛欲绝,滴血的心在呼喊着,“为什么上天要这样折磨我?为什么不让我存档?”
[Play Happy Bird](https://flappybird.io/)
想象一下你正在写代码,你今晚的目标是实现某一个新功能,不然就不睡觉。经过千辛万苦,你终于把代码写好了,保存并编译运行,你看到调试信息一行一行地在终端上输出。就要看到成功的曙光的时候,竟然发生了错误!你仔细思考,发现你之前的构思有着致命的错误,但之前正确运行的代码已经永远离你而去了。你悲痛欲绝,滴血的心在呼喊着,“为什么上天要这样折磨我?”你绝望地倒在屏幕前 ... ... 这时,你发现身边渐渐出现无数的光玉,把你包围起来,耀眼的光芒令你无法睁开眼睛 ... ... 等到你回过神来,你发现屏幕上正是那份之前正确运行的代码!但在你的记忆中,你确实经历过那悲痛欲绝的时刻 ... ... 这一切真是不可思议啊 ... ...
## <strong>人生如戏</strong><strong></strong><strong>戏如人生</strong>
## 人生如戏,戏如人生
人生就像不能重玩的 Flappy Bird但软件工程领域却并非如此而那不可思议的光玉就是“版本控制系统”。版本控制系统给你的开发流程提供了比朋也收集的更强大的光玉能够让你在过去和未来中随意穿梭避免上文中的悲剧降临你的身上。
@@ -16,13 +18,13 @@
在本节,我们使用 `git` 进行版本控制。下面简单介绍如何使用 `git`
### <strong>游戏设置</strong>
### 游戏设置
首先你得安装 `git` :
- Linux 下
```
```bash
# Debian , Ubuntu
sudo apt install git
```
@@ -35,26 +37,26 @@ sudo apt install git
安装好之后,你需要先进行一些配置工作。在终端里输入以下命令:
```
```bash
git config --global user.name "Zhang San" # your name
git config --global user.email "zhangsan@foo.com" # your email
```
经过这些配置, 你就可以开始使用 `git` 了。
经过这些配置你就可以开始使用 `git` 了。
你会通过 `git clone` 命令来拉取远程仓库的代码,里面已经包含一些 `git` 记录,因此不需要额外进行初始化。如果你想在别的实验、项目中使用 `git` ,你首先需要切换到实验、项目的目录中,然后输入
```
```bash
git init
```
进行初始化。初始化后会创建一个隐藏的文件夹名为 `.git` git 会基于这个文件夹来进行版本控制功能。
### <strong>查看</strong><strong>commit</strong><strong>信息</strong>
### 查看 commit 信息
使用
```
```bash
git log
```
@@ -64,35 +66,35 @@ git log
使用
```
```bash
git status
```
可以得知,与当前存档相比,哪些文件发生了变化.
可以得知,与当前存档相比,哪些文件发生了变化
### 提交
你可以像以前一样编写代码。等到你的开发取得了一些阶段性成果,你应该马上进行提交( commit )”。
你可以像以前一样编写代码。等到你的开发取得了一些阶段性成果,你应该马上进行提交commit”。
首先你需要使用 `git status` 查看是否有新的文件或已修改的文件未被跟踪;若有,则使用 `git add` 将文件加入跟踪列表,例如
```
```bash
git add file.c
```
会将 `file.c` 加入跟踪列表。如果需要一次添加所有未被跟踪的文件,你可以使用
会将 `file.c` 加入**跟踪列表**。如果需要一次添加所有未被跟踪的文件,你可以使用
```
```bash
git add -A
# or
# 或者
git add .
```
但这样可能会跟踪了一些不必要的文件(二进制文件),例如编译产生的 `.o` 文件,和最后产生的可执行文件。事实上,我们只需要跟踪代码源文件即可。为了让 `git` 在添加跟踪文件之前作筛选,你可以编辑 `.gitignore` 文件( 没有的话手动创建 文件名就叫这个 ),在里面给出需要被 `git` 忽略的文件和文件类型。
但这样可能会跟踪了一些不必要的文件(二进制文件),例如编译产生的 `.o` 文件,和最后产生的可执行文件。事实上,我们只需要跟踪代码源文件即可。为了让 `git` 在添加跟踪文件之前作筛选,你可以编辑 `.gitignore` 文件(没有的话手动创建 文件名就叫这个),在里面给出需要被 `git` 忽略的文件和文件类型。
这个网页可以根据你搜索的语言来给你创建必要的 `.gitignore` 文件
[这个网页](https://www.toptal.com/developers/gitignore) 可以根据你搜索的语言来给你创建必要的 `.gitignore` 文件
```
```bash
# .gitignore文件示例
.idea # 编辑器配置
__pycache__ # 缓存文件夹
@@ -105,15 +107,15 @@ file.o # 一个编译后的文件
建议把编译后的文件都加入 `.gitignore` 并在 `README.md` 文件中留下编译的详细操作流程,节省 `.git` 空间、符合提交规范。
把新文件加入跟踪列表后, 使用 `git status` 再次确认. 确认无误后就可以存档了, 使用
把新文件加入跟踪列表后使用 `git status` 再次确认确认无误后就可以存档了使用
```
```bash
git commit -m "...comment..."
```
提交工程当前的状态(注释)。其中 `...comment...` 是你本次提交的注释( 一般在注释中简略写出本次提交干了什么)以下为注释规范,养成良好习惯请遵守:
提交工程当前的状态(注释)。其中 `...comment...` 是你本次提交的注释(一般在注释中简略写出本次提交干了什么)以下为注释规范,养成良好习惯请遵守:
```
```bash
模板:
type(scope): subject
@@ -125,7 +127,7 @@ type为commit的类型
style: 代码格式修改
test: 测试用例修改
chore: 其他修改, 比如构建流程, 依赖管理.
pref: 性能提升的修改
perf: 性能提升的修改
build: 对项目构建或者依赖的改动
ci: CI 的修改ci是自动构建 感兴趣可以搜搜 github workflow
revert: revert 前一个 commit 撤销前一个commit
@@ -143,33 +145,35 @@ subject为commit概述
其中详细内容可以参照 [约定式提交](https://www.conventionalcommits.org/zh-hans/v1.0.0/)
附上 [语义化版本 2.0.0 规范](https://semver.org/lang/zh-CN/)
你可以使用 `git log` 查看存档记录,你应该能看到刚才编辑的注释。
### <strong>读档</strong><strong> 回溯到某一个 commit </strong>
### 读档(回溯到某一个 commit
如果你遇到了上文提到的让你悲痛欲绝的情况,现在你可以使用光玉来救你一命了。首先使用 `git log` 来查看已有的存档,并决定你需要回到哪个过去。每一份存档都有一个 `hash code`,例如 `b87c512d10348fd8f1e32ddea8ec95f87215aaa5` , 你需要通过 `hash code` 来告诉 `git` 你希望读哪一个档。使用以下命令进行读档:
```
```bash
git reset --hard b87c
```
其中 `b87c` 是上文 `hash code` 的前缀:你不需要输入整个 hash code. 这时你再看看你的代码,你已经成功地回到了过去!
但事实上, 在使用 `git reset``hard` 模式之前, 你需要再三确认选择的存档是不是你的真正目标。 如果你读入了一个较早的存档,那么比这个存档新的所有记录都将被删除!这意味着你不能随便回到“将来”了。
但事实上在使用 `git reset``hard` 模式之前你需要再三确认选择的存档是不是你的真正目标。如果你读入了一个较早的存档,那么比这个存档新的所有记录都将被删除!这意味着你不能随便回到“将来”了。
### 分支
当然还是有办法来避免上文提到的副作用的,这就是 `git` 的分支功能。使用命令:
```
```bash
git branch
```
查看所有分支. 其中 `master` 是主分支,使用 `git init` 初始化之后会自动建立主分支。
查看所有分支其中 `master` 是主分支,使用 `git init` 初始化之后会自动建立主分支。
读档的时候使用以下命令:
```
```bash
git checkout b87c
```
@@ -178,88 +182,193 @@ git checkout b87c
- 查看 `b87c` 存档的内容
- 使用以下命令切换到其它分支
```
```bash
git checkout 分支名
```
- 对代码的内容进行修改,但你不能使用 `git commit` 进行存档,你需要使用
```
```bash
git checkout -B 分支名
```
- 把修改结果保存到一个新的分支中,如果分支已存在,其内容将会被覆盖
不同的分支之间不会相互干扰,这也给项目的分布式开发带来了便利。有了分支功能,你就可以像第三视点那样在一个世界的不同时间 ( 一个分支的多个存档 ),或者是多个平行世界 多个分支 之间来回穿梭了。
不同的分支之间不会相互干扰,这也给项目的分布式开发带来了便利。有了分支功能,你就可以像第三视点那样在一个世界的不同时间 ( 一个分支的多个存档 ),或者是多个平行世界多个分支之间来回穿梭了。
### <strong>更多功能</strong>
### 更多功能
以上介绍的是 `git` 的一些基本功能,`git` 还提供很多强大的功能,例如使用 `git diff` 比较同一个文件在不同版本中的区别,使用 `git bisect` 进行二分搜索来寻找一个 bug 在哪次提交中被引入...
其它功能的使用请参考 `git help` `man git` 或者在网上搜索相关资料。
其它功能的使用请参考 `git help` `man git` ,或者在网上搜索相关资料。
## 全球最大男性交友网站 —— Github
::: tip 🤡
想象一下你正在进行人生中第一次软件开发的小组合作。
你把任务分配好让组员去写代码中的某一个模块。组员写好之后发给你。
你一看,通过 QQ 发过来的是一个文件啊文件 比如说 `学生管理模块.c` 你打开一看,我去是**乱码**。
你废了九牛二虎之力把他的 GBK 编码改成 UTF8 之后,细细地品鉴这段代码,发现我去有严重逻辑错误,而且代码很不规范。
你通过 QQ 告诉他,这一行有问题,能不能改一下。他说,好的我改一下。
然后又发了文件啊文件给你,如此反复循环,你俩已经互相传了好几百个源代码文件,很没效率!
:::
> 通过 Git 版本控制管理自己的代码,再通过 Github 来发布、同步互联,是一个很好的解决方案!
简介
作为开源代码库以及版本控制系统Github 拥有超过 900 万开发者用户。随着越来越多的应用程序转移到了云上Github 已经成为了管理软件开发以及发现已有代码的首选方法。
页面大概是这样:
页面大概是这样(老图)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnHemi9HkeAG1fgoznHbHLrc.png)
![](https://cdn.xyxsw.site/boxcnHemi9HkeAG1fgoznHbHLrc.png)
### Git 和 Github
[GitHub](https://github.com/)[ ](https://github.com/)是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub。
[GitHub](https://github.com/)是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub。
### Git 绑定 Github
::: tip 🤗
下面将教学如何注册这个网站,并给[本项目](https://github.com/camera-2018/hdu-cs-wiki)点一个小小的 kita kita 的 star🎇
:::
#### 第一步:注册账号
[GitHub 官网](https://github.com/))右上角 sign up 会有一个非常酷炫的界面指引你注册 🥳
[GitHub 官网](https://github.com/))右上角点击 sign up 会有一个非常酷炫的界面指引你注册 🥳
#### 第二步:创建 SSH Key 并获取公钥
他会用一个像是命令行交互的方式引导注册,你需要依次填写 `邮箱``密码``用户名(此为 ID 非昵称)``是否同意邮箱广告推送``机器验证码` 之后创建账户,随后会给你填写的邮箱发送验证码,填写注册。
先在 C:\Users\用户名\.ssh 下找有没有 `id_rsa``id_rsa.pub` 文件
随后是一个欢迎问卷😋随便填写、如果他问你什么 PRO Plan 选择 free 不付费就好。
最后你访问[GitHub 官网](https://github.com)应该会显示你的 dashboard 管理台界面
#### 第二步:选择你拉取仓库的方式
点开 github 某个仓库的绿油油的 `<>Code` 按钮,你会发现有三种 clone 方式。
分别为
- https基本无配置有图形化界面就能用
- ssh有公私钥设置没有图形化界面也能用
- gh-cligithub 出品的 cli 工具)
![](https://cdn.xyxsw.site/Snipaste_2023-08-27_14-06-28.png)
#### 【https 方法配置】账号绑定 github
在命令行配置好你的 id 和邮箱
```bash
git config --global user.name "Zhang San" # your name
git config --global user.email "zhangsan@foo.com" # your email
```
在 GitHub 主页,找到 `New` 或者 `Create repository` 一个绿色的按钮,创建一个新的仓库
![](https://cdn.xyxsw.site/boxcn5sVnE76FYpVW2RDxtWDiZc.png)
然后填上这个仓库的大名就可以创建了
![](https://cdn.xyxsw.site/boxcnsN133WrLrbxsX8JgvsQmif.png)
进入你新创建的仓库
跟随新创建之后的指引,`…or create a new repository on the command line` 内他描述了如何创建一个文件夹、创建一个 README.md 的文件,然后和 github 仓库绑定。
push 的时候 github 会弹窗索要你的 github 个人信息,如下图
![](https://cdn.xyxsw.site/image_32.png)
输入你的 github 用户名
![](https://cdn.xyxsw.site/image_33.png)
但如果这个时候输入你的账户密码,就会出现如下提示
![](https://cdn.xyxsw.site/image_35.png)
这是因为 github 在 2021 年 8 月 13 日之后移除了对密码验证的支持,你需要使用令牌认证的方式
进入个人设置,拉到最底下
![](https://cdn.xyxsw.site/image_36.png)
选择
![](https://cdn.xyxsw.site/image_37.png)
![](https://cdn.xyxsw.site/image_38.png)
会看到这样一个界面
![](https://cdn.xyxsw.site/image_39.png)
可以随便起一个名字,选择 token 的有效期,然后给这个 token 一些权限,如果不清楚这些选项分别代表什么意思的话,把 repo 这个勾选一般就足够了。
:::warning
这个令牌只会在生成时可见,之后就不会再显示了,请做好复制并保存
:::
这样我们就可以使用 token 来进行 https 方法绑定 github 账号
![](https://cdn.xyxsw.site/image_40.png)
#### 【ssh 方法配置】创建 SSH Key 并获取公钥
先在 `C:\Users\用户名\.ssh` 下找有没有 `id_rsa``id_rsa.pub` 文件
:::tip
这里 `.ssh` 文件夹是一个隐藏文件夹
如何显示隐藏文件夹请搜索互联网或看这篇文章 [support microsoft 显示隐藏的文件](https://support.microsoft.com/zh-cn/windows/%E6%98%BE%E7%A4%BA%E9%9A%90%E8%97%8F%E7%9A%84%E6%96%87%E4%BB%B6-0320fe58-0117-fd59-6851-9b7f9840fdb2)
:::
如果有就直接跳过这一步
如果没有,打开 Shell Windows 下打开 Git Bash <em>前提是你已经安装好了 git 在桌面右键应该会有 Git bash here 选项 </em>),创建 SSH Key
如果没有,打开 ShellWindows 下打开 Git Bash *前提是你已经安装好了 git 在桌面右键应该会有 Git bash here 选项*),创建 SSH Key
```powershell
```bash
ssh-keygen -t rsa -C "youremail@example.com" # youremail为你注册用的电子邮件地址
```
打开 `id_rsa.pub`,复制里面的内容
#### 第三步:绑定 Github
#### 【ssh 方法配置】绑定 Github
登陆 `GitHub`,打开 `settings`
登陆 `GitHub`点击右上角自己的头像,打开 `settings`
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn9VFPUYHl8ghJ3C78RsXjtf.png)
![](https://cdn.xyxsw.site/Snipaste_2023-07-16_17-12-32.png)
然后打开左侧栏 `SSH and GPG`` keys` 页面
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn1HbQct335qvZ71tGNu7jne.png)
![](https://cdn.xyxsw.site/boxcn1HbQct335qvZ71tGNu7jne.png)
然后,点 `New SSH Key`,填上任意 Title在 Key 文本框里粘贴 `id_rsa.pub` 文件的内容即可
#### 第四步:创建仓库并和本地绑定
#### 【ssh 方法配置】创建仓库并和本地绑定
绑定完 GitHub 然后你可以创建仓库了
首先在 GitHub 主页,找到 “New” 按钮,创建一个新的仓库
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn5sVnE76FYpVW2RDxtWDiZc.png)
首先在 GitHub 主页,找到 `New` 或者 `Create repository` 一个绿色的按钮,创建一个新的仓库
![](https://cdn.xyxsw.site/boxcn5sVnE76FYpVW2RDxtWDiZc.png)
然后填上这个仓库的大名就可以创建了
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnsN133WrLrbxsX8JgvsQmif.png)
![](https://cdn.xyxsw.site/boxcnsN133WrLrbxsX8JgvsQmif.png)
根据之前学习的方法在本地创建完 git 仓库之后
在 git bash 中输入:
```powershell
```bash
git remote add origin git@github.com:yourname/gitexample.git
# 请将yourname换成自己的id
```
@@ -268,45 +377,57 @@ git remote add origin git@github.com:yourname/gitexample.git
或者是直接 git clone 下来
```powershell
```bash
git clone git@github.com:yourname/gitexample.git
```
或者你可以跟随新创建之后的指引,`…or create a new repository on the command line` 内他描述了如何创建一个文件夹、创建一个 README.md 的文件,然后和 github 仓库绑定。
![](https://cdn.xyxsw.site/Snipaste_2023-07-16_17-19-18.png)
### 下载代码——clone
拷贝他人存档也未尝不可,而我们如果用他人存档时,次次都需要一样一样的拷贝文件和代码未免太过折磨,下面简单介绍如何使用
```powershell
git clone [url]
```bash
git clone <url>
```
接下去对着下面这个 GitHub 的代码使用一下
首先,代码的 url 在下图所示的位置
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnTiaT2EnNfKVkretPsyajVd.png)
![](https://cdn.xyxsw.site/boxcnTiaT2EnNfKVkretPsyajVd.png)
然后复制完代码后切换回我们的命令行
```bash
e: #powershell or cmd
# 进入到想要存储该代码的地方
# powershell or cmd
# 进入cd到想要存储该代码的地方(父文件夹目录)
git clone https://github.com/camera-2018/git-example.git
```
> 这里使用的[例子](https://github.com/camera-2018/git-example)是我的仓库,当然你也可以用你自己的仓库。
>
> 如果你使用我的仓库的话,你 clone 过后在你自己电脑更改的文件等东西,是没法直接提交回来的(因为你没有我仓库管理权限)
>
> 如果你非要给我的仓库添加东西呢 也是可以,参照下面的 PRPull Request教程
一阵抽搐过后就下载好了
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn8aRDQpe7uuDxFv9v1WvZ4c.png)
![](https://cdn.xyxsw.site/boxcn8aRDQpe7uuDxFv9v1WvZ4c.png)
注意:用完之后别忘记给 camera-2018 点个 follow 呃呃 follow 没用 star 有用
::: tip
用完之后别忘记给 camera-2018 点个 follow 😋 `呃呃 follow 没用 star 有用`
:::
注意:失败就重试吧 还失败建议使用魔法
注意:失败就重试吧 还失败建议使用魔法(非国内网你懂得)
### 提交和合并分支
如图 我在仓库里新建了 `helloworld.c` 并且写了一些代码
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnZpPsp4FP78auolzHvCKP0g.png)
![](https://cdn.xyxsw.site/boxcnZpPsp4FP78auolzHvCKP0g.png)
接下来是提交操作
@@ -314,7 +435,7 @@ git clone https://github.com/camera-2018/git-example.git
git status #看一下文件暂存区
```
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnm4R1ZN0WeUBuYht6zge7pd.png)
![](https://cdn.xyxsw.site/boxcnm4R1ZN0WeUBuYht6zge7pd.png)
红色表示文件没有提交到暂存区 我们要提交
@@ -324,7 +445,7 @@ git status #看一下文件暂存区
git add . #将没有提交的所有文件加入暂存区
```
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnYHd076RAqfDmHjbUkeNSvg.png)
![](https://cdn.xyxsw.site/boxcnYHd076RAqfDmHjbUkeNSvg.png)
绿色表示所有文件已加入暂存
@@ -332,61 +453,131 @@ git add . #将没有提交的所有文件加入暂存区
git commit -m "feat(helloworld): add helloworld file"
```
将刚才加入暂区的文件发起了一个提交 注释`feat(helloworld): add helloworld file`
将刚才加入暂区的文件发起了一个提交提交注释commit message`feat(helloworld): add helloworld file`
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcni2dupDzNO8qTWPAxS5c67b.png)
![](https://cdn.xyxsw.site/boxcni2dupDzNO8qTWPAxS5c67b.png)
1. 如果这是你自己的仓库有权限 你就可以直接使用
1. 如果这是你自己的仓库有权限(本人仓库或 Collaborators 有权限的情况下)你就可以直接使用
```bash
git push origin main # origin是第四步里remote add起的远程名字
# main是分支名
```
```bash
git push origin main # origin 是第四步里 remote add 起的远程名字
# main 是分支名
```
上传本次提交
上传本次提交
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnNBu1EJnva4EkyQZAVlwGMe.png)
![](https://cdn.xyxsw.site/boxcnNBu1EJnva4EkyQZAVlwGMe.png)
1. 如果你没有本仓库的主分支提交权限 可以提交 prpull requests
2. 如果你没有本仓库的主分支提交权限 可以提交 PRPull Requests
这里假设我是协作者 无主分支权限
**第一种情况:这里假设我是协作者 无主分支权限,但有创建分支权限**
首先创建一个新分支 命名为 `yourname-dev`
首先创建一个新分支 命名为 `yourname-dev`
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnaS7aOzdt31vsZZx8R1s33e.png)
![](https://cdn.xyxsw.site/boxcnaS7aOzdt31vsZZx8R1s33e.png)
然后按照上面的方法 `git clone` 并切换到你刚创建的分支
然后按照上面的方法 `git clone` 并切换到你刚创建的分支
```bash
git switch camera-2018-dev
```
```bash
git switch camera-2018-dev
```
然后提交一个文件 这里使用 vscode 自带的 git 工具试试
然后提交一个文件这里直接使用 vscode 自带的 git 工具试试(很方便、不用敲命令行)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnmwlYWOzwPbNqTAuSZK9dW3.png)
![](https://cdn.xyxsw.site/boxcnmwlYWOzwPbNqTAuSZK9dW3.png)
点暂存所有更改 写好 comment 之后点提交
点暂存所有更改 写好 comment 之后点提交
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnfcCnAdtdX2oyLIC3NibVnf.png)
![](https://cdn.xyxsw.site/boxcnfcCnAdtdX2oyLIC3NibVnf.png)
最后点同步更改上传
最后点同步更改上传
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn9DSPlFgG2WMZhTOE9Zhzgb.png)
![](https://cdn.xyxsw.site/boxcn9DSPlFgG2WMZhTOE9Zhzgb.png)
如果是你提交 在 github 上会显示这个 快捷创建 pr 的按钮
如果是你提交 在 github 上会显示这个 快捷创建 pr 的按钮
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnHd7Qfi8C0Y7V2Ot5ii4vpf.png)
![](https://cdn.xyxsw.site/boxcnHd7Qfi8C0Y7V2Ot5ii4vpf.png)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnyt3eeZQyN8b1xM1WjDrTGe.png)
![](https://cdn.xyxsw.site/boxcnyt3eeZQyN8b1xM1WjDrTGe.png)
点它创建 pr
点它创建 PR
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnJOjh1Zfp9tCd3llL9NsEzb.png)
![](https://cdn.xyxsw.site/boxcnJOjh1Zfp9tCd3llL9NsEzb.png)
这样管理本仓库的人看到 pr 请求就可以 merge 合并辣
这样管理本仓库的人看到 pr 请求就可以 merge 合并辣
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnBMq0sw6c48jvjdPJwmAGtZ.png)
![](https://cdn.xyxsw.site/boxcnBMq0sw6c48jvjdPJwmAGtZ.png)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcngNZOSnYUtCKH6pm8UaUMNd.png)
![](https://cdn.xyxsw.site/boxcngNZOSnYUtCKH6pm8UaUMNd.png)
实际合作过程中可能会出现代码冲突无法 merge 的情况 😋 遇到了自己去 STFW 吧
实际合作过程中可能会出现代码冲突无法 merge 的情况 😋 遇到了自己去 STFW 吧
**第二种情况:我不是协作者、我什么权限也没有,我看了这个 public 项目后觉得很好但是有一些问题,我要给他贡献一些代码**
可以点击仓库右上角的 fork
![](https://cdn.xyxsw.site/Snipaste_2023-07-16_17-34-21.png)
这样会在你的名下多出来一份这个同名仓库,而这个仓库你是拥有所有权限的,你可以 clone 你这个同名仓库,更改代码,提交代码之后
回到源仓库点击 Pull Request 然后创建 PR `New pull request`
最上面会提示你说
Comparing changes
Choose two branches to see whats changed or to start a new pull request. If you need to, you can also **compare across forks** .
点击小蓝字 `compare across forks` 这会让你对比你 fork 仓库和源代码仓库的提交记录,之后就可以创建 PR 了,原作者看到了会合并。
### 其他功能
问题跟踪GitHub 的问题跟踪功能可用于报告软件中的问题、错误和功能请求,并进行讨论、分配和解决。
Wiki 页面:用户可以创建和编辑与存储库相关的 Wiki 页面,用于提供项目的文档、指南、示例代码等。
Pull 请求Pull Requests使用者可以将自己的代码变更提交给其他项目的所有者并请求合并到主干代码中。
项目管理GitHub 提供项目管理功能包括任务管理、里程碑milestones、项目板project boards等工具可用于组织和跟踪项目的进展。
部署功能GitHub 可以与各种持续集成和部署CI/CD工具集成帮助开发人员自动化构建、测试和部署他们的应用程序。
统计信息GitHub 提供有关存储库活动和贡献者的统计信息,例如提交图表、活动日历等,有助于跟踪和分析项目的发展。
社交功能:用户可以关注其他用户、存储库和组织,接收他们的更新和活动通知,并与他们进行交流和讨论。
代码审核Code ReviewGitHub 的 Pull 请求功能允许团队成员对代码进行审查和讨论,以确保代码质量和最佳实践。
集成和扩展GitHub 支持与其他工具和服务的集成例如持续集成CI工具、代码质量检查工具、项目管理工具等。
页面托管GitHub Pages 功能使您可以托管静态网站和文档,这在展示和共享项目文档、演示和博客等方面非常有用。
然后还有一些比如说 Copilot 之类的有用的功能。
[Copilot](https://github.com/features/copilot) 是 GitHub 推出的一款基于人工智能技术的代码辅助工具。它使用了机器学习模型 codex并针对编写代码的场景进行了训练。
Copilot 可以根据上下文和输入的提示,为开发人员生成代码建议和自动完成。它可以通过分析现有代码库、注释和上下文来生成代码片段,提高编码效率并减少重复劳动。
## [Copilot](https://github.com/features/copilot) 白嫖教程
你需要学生认证你的 Github 账号。
地址在 [https://education.github.com/students](https://education.github.com/students) 点击 `Sign up for Global Campus` 来开始认证,下面会让你输入学校,绑定学校邮箱(杭电为 @hdu.edu.cn 结尾的邮箱)(如果你是杭电新生的话,可能要等到智慧杭电账号发放时才能注册杭电邮箱)并上传**学生证明**(从 21 年开始这个验证越来越严,如果不过的话你可以尝试 `学生证第一页`、`学生证第一页英文翻译(像有道翻译那样 P 图上去)`、`学信网学籍证明英文翻译(英文也是 P 上去)`
通过了的话你的账户会有 Pro 标识 然后你可以享受的 Github 学生包里包含[这些东西](https://education.github.com/pack)
里面比较有用的有
- JETBRAINS 全家桶的免费用(我没用,我用的是 jb 自己家的验证方式,不是 github
- name.com 家的一个一年期的免费域名(大概价值吧 六七十块钱?)
- github 的容量扩容和 actions 时间扩容、Codespaces 时间延长、Pages 扩容(没啥用倒是)
- Termius 学生包,这是我很喜欢用的终端软件,有学生包可以多端同步 ssh 的账号密码啥的,很方便。
- Sentry 容量扩容
- Copilot 免费用
你可以在 `settings` 里看到你的 copilot配置如下
![](https://cdn.xyxsw.site/Snipaste_2023-07-16_17-59-49.png)
然后就可以在你喜欢的 IDE 或编辑器上下载 Copilot 插件,来启用他。
![](https://cdn.xyxsw.site/Snipaste_2023-07-16_18-02-19.png)

View File

@@ -1,18 +1,16 @@
# 从 CS61A 看编程语言学习
# 什么是 CS61A
## 什么是 CS61A
首先声明,本教程的 python 部分很多内容摘自 CS61A
如果你看过 CS 自学指南,想必你在第一页就看过这样的描述
> 大一入学时我是一个对计算机一无所知的小白,装了几十个 G 的 Visual Studio 天天和 OJ 你死我活。凭着高中的数学底子我数学课学得还不错,但在专业课上对竞赛大佬只有仰望。提到编程我只会打开那笨重的 IDE新建一个我也不知道具体是干啥的命令行项目然后就是 `cin`, `cout`, `for` 循环,然后 CE, RE, WA 循环。当时的我就处在一种拼命想学好但不知道怎么学,课上认真听讲但题还不会做,课后做作业完全是用时间和它硬耗的痛苦状态。我至今电脑里还存着自己大一上学期计算概论大作业的源代码 —— 一个 1200 行的 C++ 文件,没有头文件、没有类、没有封装、没有 unit test、没有 Makefile、没有 Git唯一的优点是它确实能跑缺点是“能跑”的补集。我一度怀疑我是不是不适合学计算机因为童年对于极客的所有想象已经被我第一个学期的体验彻底粉碎了。<br/>这一切的转机发生在我大一的寒假,我心血来潮想学习 Python。无意间看到知乎有人推荐了 CS61A 这门课,说是 UC Berkeley 的大一入门课程,讲的就是 Python。我永远不会忘记那一天打开 [CS61A](https://cs61a.org/) 课程网站的那个瞬间,就像哥伦布发现了新大陆一样,我开启了新世界的大门。<br/>我一口气 3 个星期上完了这门课,它让我第一次感觉到原来 CS 可以学得如此充实而有趣,原来这世上竟有如此精华的课程。<br/>为避免有崇洋媚外之嫌,我单纯从一个学生的视角来讲讲自学 CS61A 的体验:<br/>- 独立搭建的课程网站: 一个网站将所有课程资源整合一体,条理分明的课程 schedule、所有 slides, hw, discussion 的文件链接、详细明确的课程给分说明、历年的考试题与答案。这样一个网站抛开美观程度不谈,既方便学生,也让资源公正透明。<br/>- 课程教授亲自编写的教材CS61A 这门课的开课老师将 MIT 的经典教材 Structure and Interpretation of Computer Programs (SICP) 用 Python 这门语言进行改编(原教材基于 Scheme 语言),保证了课堂内容与教材内容的一致性,同时补充了更多细节,可以说诚意满满。而且全书开源,可以直接线上阅读。<br/>- 丰富到让人眼花缭乱的课程作业14 个 lab 巩固随堂知识点10 个 homework还有 4 个代码量均上千行的 project。与大家熟悉的 OJ 和 Word 文档式的作业不同,所有作业均有完善的代码框架,保姆级的作业说明。每个 Project 都有详尽的 handout 文档、全自动的评分脚本。CS61A 甚至专门开发了一个[自动化的作业提交评分系统](https://okpy.org/)(据说还发了论文)。当然,有人会说“一个 project 几千行代码大部分都是助教帮你写好的,你还能学到啥?”。此言差矣,作为一个刚刚接触计算机,连安装 Python 都磕磕绊绊的小白来说,这样完善的代码框架既可以让你专注于巩固课堂上学习到的核心知识点,又能有“我才学了一个月就能做一个小游戏了!”的成就感,还能有机会阅读学习别人高质量的代码,从而为自己所用。我觉得在低年级,这种代码框架可以说百利而无一害。唯一的害也许是苦了老师和助教,因为开发这样的作业可想而知需要相当的时间投入。<br/>- 每周 Discussion 讨论课,助教会讲解知识难点和考试例题:类似于北京大学 ICS 的小班研讨,但习题全部用 LaTeX 撰写,相当规范且会明确给出 solution。<br/>这样的课程,你完全不需要任何计算机的基础,你只需要努力、认真、花时间就够了。此前那种有劲没处使的感觉,那种付出再多时间却得不到回报的感觉,从此烟消云散。这太适合我了,我从此爱上了自学。<br/>试想如果有人能把艰深的知识点嚼碎嚼烂,用生动直白的方式呈现给你,还有那么多听起来就很 fancy种类繁多的 project 来巩固你的理论知识,你会觉得他们真的是在倾尽全力想方设法地让你完全掌握这门课,你会觉得不学好它简直是对这些课程建设者的侮辱。<br/>如果你觉得我在夸大其词,那么不妨从 [CS61A](https://cs61a.org/) 开始,因为它是我的梦开始的地方。
> 大一入学时我是一个对计算机一无所知的小白,装了几十个 G 的 Visual Studio 天天和 OJ 你死我活。凭着高中的数学底子我数学课学得还不错,但在专业课上对竞赛大佬只有仰望。提到编程我只会打开那笨重的 IDE新建一个我也不知道具体是干啥的命令行项目然后就是 `cin`, `cout`, `for` 循环,然后 CE, RE, WA 循环。当时的我就处在一种拼命想学好但不知道怎么学,课上认真听讲但题还不会做,课后做作业完全是用时间和它硬耗的痛苦状态。我至今电脑里还存着自己大一上学期计算概论大作业的源代码 —— 一个 1200 行的 C++ 文件,没有头文件、没有类、没有封装、没有 unit test、没有 Makefile、没有 Git唯一的优点是它确实能跑缺点是“能跑”的补集。我一度怀疑我是不是不适合学计算机因为童年对于极客的所有想象已经被我第一个学期的体验彻底粉碎了。<br/>这一切的转机发生在我大一的寒假,我心血来潮想学习 Python。无意间看到知乎有人推荐了 CS61A 这门课,说是 UC Berkeley 的大一入门课程,讲的就是 Python。我永远不会忘记那一天打开 [CS61A](https://cs61a.org/) 课程网站的那个瞬间,就像哥伦布发现了新大陆一样,我开启了新世界的大门。<br/>我一口气 3 个星期上完了这门课,它让我第一次感觉到原来 CS 可以学得如此充实而有趣,原来这世上竟有如此精华的课程。<br/>为避免有崇洋媚外之嫌,我单纯从一个学生的视角来讲讲自学 CS61A 的体验:<br/>- 独立搭建的课程网站一个网站将所有课程资源整合一体,条理分明的课程 schedule、所有 slides, hw, discussion 的文件链接、详细明确的课程给分说明、历年的考试题与答案。这样一个网站抛开美观程度不谈,既方便学生,也让资源公正透明。<br/>- 课程教授亲自编写的教材CS61A 这门课的开课老师将 MIT 的经典教材 Structure and Interpretation of Computer Programs (SICP) 用 Python 这门语言进行改编(原教材基于 Scheme 语言),保证了课堂内容与教材内容的一致性,同时补充了更多细节,可以说诚意满满。而且全书开源,可以直接线上阅读。<br/>- 丰富到让人眼花缭乱的课程作业14 个 lab 巩固随堂知识点10 个 homework还有 4 个代码量均上千行的 project。与大家熟悉的 OJ 和 Word 文档式的作业不同,所有作业均有完善的代码框架,保姆级的作业说明。每个 Project 都有详尽的 handout 文档、全自动的评分脚本。CS61A 甚至专门开发了一个[自动化的作业提交评分系统](https://okpy.org/)(据说还发了论文)。当然,有人会说“一个 project 几千行代码大部分都是助教帮你写好的,你还能学到啥?”。此言差矣,作为一个刚刚接触计算机,连安装 Python 都磕磕绊绊的小白来说,这样完善的代码框架既可以让你专注于巩固课堂上学习到的核心知识点,又能有“我才学了一个月就能做一个小游戏了!”的成就感,还能有机会阅读学习别人高质量的代码,从而为自己所用。我觉得在低年级,这种代码框架可以说百利而无一害。唯一的害也许是苦了老师和助教,因为开发这样的作业可想而知需要相当的时间投入。<br/>- 每周 Discussion 讨论课,助教会讲解知识难点和考试例题:类似于北京大学 ICS 的小班研讨,但习题全部用 LaTeX 撰写,相当规范且会明确给出 solution。<br/>这样的课程,你完全不需要任何计算机的基础,你只需要努力、认真、花时间就够了。此前那种有劲没处使的感觉,那种付出再多时间却得不到回报的感觉,从此烟消云散。这太适合我了,我从此爱上了自学。<br/>试想如果有人能把艰深的知识点嚼碎嚼烂,用生动直白的方式呈现给你,还有那么多听起来就很 fancy种类繁多的 project 来巩固你的理论知识,你会觉得他们真的是在倾尽全力想方设法地让你完全掌握这门课,你会觉得不学好它简直是对这些课程建设者的侮辱。<br/>如果你觉得我在夸大其词,那么不妨从 [CS61A](https://cs61a.org/) 开始,因为它是我的梦开始的地方。
如果看完了这些你可能会震惊会怀疑并且试着打开它并且去尝试这门课程但是也有可能你会被纯英文的视频或者油管劝退也有可能你会怀疑我在使用别人的课程体系的前提下仍然要把它放到自己的内容里面的目的That's all right,我会在下面对她讲的东西进行一定的补充,并且附着上自己的学习建议以及学习思考。
如果看完了这些你可能会震惊会怀疑并且试着打开它并且去尝试这门课程但是也有可能你会被纯英文的视频或者油管劝退也有可能你会怀疑我在使用别人的课程体系的前提下仍然要把它放到自己的内容里面的目的That's all right我会在下面对她讲的东西进行一定的补充,并且附着上自己的学习建议以及学习思考。
# 错误的学习方式
## 错误的学习方式
很多人看到要自学 python 之后,第一时间想到的是,我要去 B 站/百度搜一搜,然后一般搜出来就是菜鸟教程,然后就是一连串枯燥乏味的知识堆叠,或者说是培训班的网课,给我们一种知识好像就是这么枯燥乏味以及自己好像学到了很多但是真的用起来却一无所知痛苦万分的感觉。
@@ -24,17 +22,17 @@
是很好。
但是为什么坚持不下来呢?
但是为什么坚持不下来呢
根据我的统计,原因无外乎是以下几点:英语太难太劝退了!课程设置太难,好像听懂了但是写起东西来却还是推行不下去!我不知道学了这个能干什么,所以没有动力!学了一两章虽然好像学到了东西,但是感觉有很多东西学了却记不住,导致难度曲线陡增了!<del>游戏太好玩了!</del>
舒适区看起来很难打破!
# 正确的思考方式
## 正确的思考方式
面对英语,我们前文有过一而再再而三的提醒过使用正确的工具,但是不得不说的是,在翻译的过程中可能难免丢失了一定的信息,使得我们在困惑中可能变得没有了前进的动力,或者从另一个角度来说我们没有动力是因为没有足够的原因来告诉我们的意识,我们到底应该在做这个超过看菜鸟教程所需精力好多倍的工作,到底能得到除了一点新奇感以外的什么东西,以此来给我们更为充分的理由支撑自己学习完成。
# 建立正确的认知论
## 建立正确的认知论
编程思想本身远比学习某一门编程语言的具体内容更为重要,我们很多的同学在进行这方面内容的时候总是只想着记忆某一门语言的某些内容,然后学的非常的痛苦。
@@ -42,12 +40,10 @@
但是编程语言的设计思想一般不会出现太大的波动,并且就算是发展也有其适配的场景和知识脉络的,如果你乐于去发掘这个知识脉络和思想,那么你就可以优雅的掌握一种思维方式而不是简单的拧螺丝一样的机械化工作。而好的思考方式往往是可以应用在同类的所有语言甚至是在所有的更多的
# 更有趣的练习方式
## 更有趣的练习方式
我不得不承认的一点是,越痛苦的练习往往可以让你获得更大的提升模拟的成长往往与你面对苦难以及解决他的时间是成正比的。
不过遗憾的是,我们大多数的同学是在面对跳起来都够不到的反馈的时候,会选择放弃。(除非你有 M 的倾向)
因此,有时候我们说大道至简。好的东西往往是能让人们快速理解的东西,我觉得 61A 的难度梯度设计,就是兼具了趣味性和间接性的,并且全面优于互联网上的非常多的教程,比硬啃要给我们更多的正反馈(当然,改变思维和学习方式是很重要的。
#

View File

@@ -2,50 +2,44 @@
当你开始制作大型项目或者复现论文时,环境配置就开始变得至关重要。
# 什么是环境?
## 什么是环境?
环境是<strong>包的集合</strong>,我们一般用 Anaconda 来配置虚拟环境。
环境是**包的集合**,我们一般用 Anaconda 来配置虚拟环境。
[戳这里安装](https://www.anaconda.com/)
装下来之后具体操作可以看[安装教程](https://blog.csdn.net/in546/article/details/117400839),如果自动配置环境变量的选项是灰色的话,请按照下面的教程把下面的几个文件路径加入环境变量。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn3PLPIvKSSvYiCnwx50FYvf.png)
![](https://cdn.xyxsw.site/boxcn3PLPIvKSSvYiCnwx50FYvf.png)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnvTQPcmPpUonmDZFZXNnGWd.png)
![](https://cdn.xyxsw.site/boxcnvTQPcmPpUonmDZFZXNnGWd.png)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn6ZnAzhaj2Tj7xk9K6FxBJh.png)
![](https://cdn.xyxsw.site/boxcn6ZnAzhaj2Tj7xk9K6FxBJh.png)
在里面添加并写入文件路径加入就好了~
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnnsuoHmhK4dBCLHlKhpRWIe.png)
![](https://cdn.xyxsw.site/boxcnnsuoHmhK4dBCLHlKhpRWIe.png)
然后打开 Pycharm创建新项目设置按照以下方式操作记得挂梯子。
如果不挂梯子,请按照教程配置清华源。[我是教程](https://blog.csdn.net/jasneik/article/details/114227716)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnTfvjYweuIZFKlcH78X38Pd.png)
![](https://cdn.xyxsw.site/boxcnTfvjYweuIZFKlcH78X38Pd.png)
然后一个新的环境就创建好辣~
# 如何配置环境
## 如何配置环境
## 1.配置你自己的环境
### 1.配置你自己的环境
你可以尝试命令 `pip install <包的名字>` 或者 `conda install <包的名字>`
```
在下载某个包失败的时候可以查一查有没有人写相关攻略~
```
> 在下载某个包失败的时候可以查一查有没有人写相关攻略~
你可以用 `conda list` 查看你这个环境已有的包。你也可以在包的名字后面加上 `==版本号` 来指定版本。
```
请注意各个包之间的依赖关系,否则容易导致无法运行或效果变差!
```
> 请注意各个包之间的依赖关系,否则容易导致无法运行或效果变差!
## 2.复现论文代码时配置环境
### 2.复现论文代码时配置环境
```
一般我们可以在Github的README中找到环境的配置方法遇到难以下载的特殊版本包时可以考虑下载它的源码手动编译具体流程不展开了可以自行搜索
```
> 一般我们可以在 Github 的 README 中找到环境的配置方法,遇到难以下载的特殊版本包时可以考虑下载它的源码手动编译,具体流程不展开了,可以自行搜索

View File

@@ -1,12 +1,17 @@
# 安装 python
教程
::: warning 😍 教程
[Python 小白必看,非常生动的 Pycharm 与 Anaconda 安装教学干货_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1Bp4y117UW?p=1&share_medium=android&share_plat=android&share_source=COPY&share_tag=s_i&timestamp=1623240637&unique_k=vHC5Wg)
[Python 小白必看,非常生动的 Pycharm 与 Anaconda 安装教学干货_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1Bp4y117UW)
[Win10 下 Conda-Pycharm-Pytorch 的安装_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV15U4y1J7Ss?from=search&seid=1987861827719523712&spm_id_from=333.337.0.0)
<Bilibili bvid='BV1Bp4y117UW'/>
# 巧妇难为无米之炊
[Win10 下 Conda-Pycharm-Pytorch 的安装_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV15U4y1J7Ss)
<Bilibili bvid='BV15U4y1J7Ss'/>
:::
## 巧妇难为无米之炊
你可以在终端上用 Python 解释器
@@ -16,27 +21,27 @@
我们推荐你都进行一波尝试,同样这也会作为一个任务
# 解释器
::: warning <font size=5>😐 解释器</font>
# Windows 用户
<font size=5><strong>Windows 用户</strong></font>
打开 [Python 官方网站](https://www.python.org/)找到“Download”里的“Latest: Python 3.x.y”。
<strong>下载完成后请大家按照下图的示意务必勾选“Add Python 3.x to PATH”然后再点击“Install Now”等待安装完成后关闭安装程序。</strong>
**下载完成后请大家按照下图的示意务必勾选“Add Python 3.x to PATH”然后再点击“Install Now”等待安装完成后关闭安装程序。**
<strong>注意windows11 安装好后 命令行输入 python 可能会跳到 Microsoft 应用商店 可在 customize installation自定义安装next 勾选 install for all users</strong>
**注意windows11 安装好后 命令行输入 python 可能会跳到 Microsoft 应用商店 可在 customize installation自定义安装next 勾选 install for all users**
## GNU/Linux 系统
<font size=5>**GNU/Linux 系统**</font>
在终端输入 `sudo apt install python3` 即可完成 Python3 的全部安装流程
可以输入 `python3 --version` 检验是否成功。
:::
![](https://cdn.xyxsw.site/boxcn95LbcwuMC2dIViOxWk8BFb.png)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcn95LbcwuMC2dIViOxWk8BFb.png)
::: warning 🤔 Jupyter Notebook
# Jupyter Notebook
[官方网站](https://jupyter.org/) Jupyter Notebook 是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。——[Jupyter ](https://link.zhihu.com/?target=https%3A//jupyter-notebook.readthedocs.io/en/stable/notebook.html)
[官方网站](https://jupyter.org/) Jupyter Notebook 是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。——[Jupyter](https://link.zhihu.com/?target=https%3A//jupyter-notebook.readthedocs.io/en/stable/notebook.html)
你在一个框框中直接输入代码,运行,它立马就在下面给你输出。怎么样,是不是很酷?
@@ -49,7 +54,8 @@
jupyter notebook
进行使用
:::
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnfwk8gnFAHu5JzVUiugJjQe.png)
![](https://cdn.xyxsw.site/boxcnfwk8gnFAHu5JzVUiugJjQe.png)
[Pycharm](https://www.jetbrains.com/zh-cn/pycharm/):可能很多同学已经用上了,我在这里不做更多解释

View File

@@ -1,10 +1,11 @@
# 阶段零Python 解释器
可参考资料
::: warning 😍 可参考资料
[官方文档](https://wiki.python.org/moin/BeginnersGuide)
[菜鸟教程](https://www.runoob.com/python3/python3-interpreter.html)
:::
你可以在终端与解释器进行交互
@@ -14,65 +15,44 @@
你可以自己把玩一下
```
```python
>>> 1 + 2
```
```
3
```
```
```python
>>> 3 - 2
```
```
1
```
```
```python
>>> 5 * 6
```
```
30
```
```
```python
>>> 7 / 4
```
```
1.75
```
```
```python
>>> 7 // 4
```
```
1
```
```
```python
>>> 7 % 4
```
```
3
```
```
>>> 4**3
```
```
```python
>>> 4 ** 3
64
```
同时可以输入 `exit``()` 或按 Ctrl+D 退出交互
同学们可能已经发现 python 这门编程语言的神奇之处了
:::: warning 🤔 同学们可能已经发现 python 这门编程语言的神奇之处了
在这里留一个思考题

View File

@@ -1,10 +1,11 @@
# 阶段一:熟悉语句
在进行本章之前,请你谨记一个原则:基本所有的功能都被人提前实现好了
::: warning 🐱 在进行本章之前,请你谨记一个原则:基本所有的功能都被人提前实现好了
你需要关心的仅仅是逻辑该如何设立
在做本章任务前,请熟悉 python 的函数,循环和判断语句即可
:::
P1请仅使用一行语句求出三个数的最小平方和
@@ -30,7 +31,7 @@ def two_of_three(x, y, z):
return _____
```
提示:可以使用 max()函数哦
提示:可以使用 `min()` 函数哦
P2下降阶乘

View File

@@ -2,17 +2,15 @@
什么是递归呢?
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnCNpeAE9Hy61cyvtxfioIHg.png)
![](https://cdn.xyxsw.site/boxcnCNpeAE9Hy61cyvtxfioIHg.png)
#
# 释义
## 释义
递归是在函数主体中重复调用函数的基本方案
让我们来看一个经典的例子
> 阶乘,即 n=n*(n-1)*......*2*1<br/>例如: `5! = 5 * 4 * 3 * 2 * 1 = 120`.
> 阶乘,即 n! =n \* (n - 1) \*...... \* 2 \* 1<br/>例如5! = 5 \* 4 \* 3 \* 2 \* 1 = 120.
而阶乘的代码如下编辑
@@ -29,9 +27,9 @@ def factorial(n):
- 想想在最简单的情况下函数将如何跳转
- 考虑使用问题的更简单版本来进行解决问题
# 任务
## 任务
P4编写一个递归函数 `skip_add`,它接受一个参数 n 并返回 `n + n-2 + n-4 + n-6 + ... + 0`。假设 n 是非负数。
P4编写一个递归函数 `skip_add`,它接受一个参数 n 并返回 `n + n-2 + n-4 + n-6 +...+ 0`。假设 n 是非负数。
```python
def skip_add(n):

View File

@@ -1,12 +1,13 @@
# 阶段三:数据抽象
数据抽象Data Abstraction)
数据抽象 (Data Abstraction)
[可参考教程](https://zhuanlan.zhihu.com/p/343133774)
::: warning 🐱 [可参考教程](https://zhuanlan.zhihu.com/p/343133774)
各位需要认真了解以下内容,他们是构建任何大厦的基石
:::
# Data Abstraction
## Data Abstraction
数据抽象是一个伟大的概念,它允许程序员将代码以对象的形式进行看待,并且从更高的层面去审视问题。
@@ -14,14 +15,14 @@
举个例子:你在开车时,如果要控制发动机的活塞怎么动,对你来说是否有些太过于困难了。因此将其抽象成了离合器,油门,刹车这些较为简单的操作。
# 组成
## 组成
一个抽象的数据类型ADT由两个主要部分组成
- Constructors:架构抽象数据类型的主要函数
- Selectors:操作数据类型的各式方法
# 列表与元组
## 列表与元组
列表是可以存储多个元素的 Python 数据结构。每个元素可以是任何类型,甚至可以是另一个列表!
@@ -37,12 +38,12 @@
```python
tup = (1, 2, 3, 4)
new_tup = tup + (5, ) # 创建新的元组new_tup并依次填充原元组的值
new_tup = tup + (5, ) # 创建新的元组 new_tup并依次填充原元组的值
new _tup
(1, 2, 3, 4, 5)
l = [1, 2, 3, 4]
l.append(5) # 添加元素5到原列表的末尾
l.append(5) # 添加元素 5 到原列表的末尾
l
[1, 2, 3, 4, 5]
```
@@ -69,13 +70,14 @@ l
3
```
思考题:
::: warning 🤔 思考题:
列表和元组在性能上有什么差异呢?
他们对应的使用场景有哪些呢?
:::
# 字典与集合
## ;ltyi 字典与集合
字典是一系列由键key和值value配对组成的元素的集合在 Python3.7+,字典被确定为有序
@@ -112,29 +114,30 @@ d
{'name': 'jason', 'age': 20, 'gender': 'male'}
s = {1, 2, 3}
s.add(4) # 增加元素4到集合
s.add(4) # 增加元素 4 到集合
s
{1, 2, 3, 4}
s.remove(4) # 从集合中删除元素4
s.remove(4) # 从集合中删除元素 4
s
{1, 2, 3}
```
思考题:
::: warning 🤔 思考题:
字典和集合分别是什么原理呢?
字典可以是一个列表吗?为什么?
:::
# 可变性
## 可变性
我们说如果一个对象可以由代码进行操作而改变那么我们称其具有可变性。
可变对象的示例包括列表和字典。不可变对象的示例包括元组和函数。
我们假定已经知道了如何使用 `==` 运算符来检查两个表达式的计算结果是否<strong>相同</strong>
我们假定已经知道了如何使用 `==` 运算符来检查两个表达式的计算结果是否**相同**
我们现在引入一个新的比较运算符 `is`,它检查两个表达式的计算结果是否<strong>相同</strong>
我们现在引入一个新的比较运算符 `is`,它检查两个表达式的计算结果是否**相同**
```python
>>> 2 + 2 == 3 + 1
@@ -176,15 +179,16 @@ False
True
```
思考题,你能否从指针的角度去理解可变性呢?
::: warning 🤔 思考题,你能否从指针的角度去理解可变性呢?
:::
# 任务
## 任务
P79*9 乘法表
P7:9*9 乘法表
可能现在对你来说,构建像下图这样的 99 乘法表已经是非常容易的一件事了,可是如果我要求你使用 python 的列表推导式(list comprehension),在两行以内完成呢?
可能现在对你来说,构建像下图这样的 99 乘法表已经是非常容易的一件事了,可是如果我要求你使用 python 的列表推导式 (list comprehension),在两行以内完成呢?
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/boxcnccDSRQj5W3lZWEUkCOHz2b.png)
![](https://cdn.xyxsw.site/boxcnccDSRQj5W3lZWEUkCOHz2b.png)
P8couple 情侣
@@ -235,40 +239,40 @@ make_city(name, lat, lon)
```python
def make_city(name, lat, lon):
<em>"""</em>
<em> >>> city = make_city('Berkeley', 0, 1)</em>
<em> >>> get_name(city)</em>
<em> 'Berkeley'</em>
<em> >>> get_lat(city)</em>
<em> 0</em>
<em> >>> get_lon(city)</em>
<em> 1</em>
<em> """</em>
<em> </em>return [name, lat, lon]
"""
>>> city = make_city('Berkeley', 0, 1
>>> get_name(city)
'Berkeley
>>> get_lat(city)
0
>>> get_lon(city)
1
"""
return [name, lat, lon]
def get_name(city):
<em>"""</em>
<em> >>> city = make_city('Berkeley', 0, 1)</em>
<em> >>> get_name(city)</em>
<em> 'Berkeley'</em>
<em> """</em>
<em> </em>return city[0]
"""
>>> city = make_city('Berkeley', 0, 1)
>>> get_name(city)
'Berkeley'
"""
return city[0]
def get_lat(city):
<em>"""</em>
<em> >>> city = make_city('Berkeley', 0, 1)</em>
<em> >>> get_lat(city)</em>
<em> 0</em>
<em> """</em>
<em> </em>return city[1]
"""
>>> city = make_city('Berkeley', 0, 1)
>>> get_lat(city)
0
"""
return city[1]
def get_lon(city):
<em>"""</em>
<em> >>> city = make_city('Berkeley', 0, 1)</em>
<em> >>> get_lon(city)</em>
<em> 1</em>
<em> """</em>
<em> </em>return city[2]
"""
>>> city = make_city('Berkeley', 0, 1)
>>> get_lon(city)
1
"""
return city[2]
```
首先你试试求出两个地方的距离。

View File

@@ -1,24 +1,25 @@
# 阶段四:高阶函数
阅读以及完成本部分内容可以帮助你有效减少代码冗余。
::: warning 🐱 阅读以及完成本部分内容可以帮助你有效减少代码冗余。
让你完成更为优雅的代码
各位要记住的是
# 代码首先是给人看的
<font size=5><strong>代码首先是给人看的</strong></font>
机器看的永远只是你的机器码。
可参考教程 [Lambda](https://zhuanlan.zhihu.com/p/80960485)
:::
# Lambda 介绍
## Lambda 介绍
Lambda 表达式是通过指定两件事来评估函数的表达式:参数和返回表达式。
请尝试阅读以下英文表格,对比函数与 lambda 表达式的不同
# Lambda 实验
## Lambda 实验
以下代码 python 会显示什么?通过对这些代码的实验,加深你对代码的学习
@@ -74,7 +75,7 @@ ______
______
```
# 任务
## 任务
P9:我们发现以下两个函数看起来实现的非常相似,是否可以进行改进,将其整合?
@@ -113,11 +114,11 @@ def is_prime(n):
需求:
你需要通过自己写一个函数: `count_cond` ,来接受一个含有两个参数的函数 `condition(n, i)`(使用lambda表达式)
你需要通过自己写一个函数: `count_cond` ,来接受一个含有两个参数的函数 `condition(n, i)`(使用 lambda 表达式)
`condition`函数应该满足第一个参数为N而第二个参数将会在`condition`函数中遍历 1 to N。
`condition`函数应该满足第一个参数为 N而第二个参数将会在`condition`函数中遍历 1 to N。
`count_cond` 将返回一个单参数函数(ps一个匿名函数),此单参数函数将会在被调用时返回 1 to N 中所有满足`condition`的数字的个数(如1到n中素数的个数)。
`count_cond` 将返回一个单参数函数 (ps一个匿名函数),此单参数函数将会在被调用时返回 1 to N 中所有满足`condition`的数字的个数 (如1 到 n 中素数的个数)。
```python
def count_cond(condition):

View File

@@ -1,6 +1,6 @@
# 阶段五:迭代生成
# 前言
## 前言
在写乘法表的时候,你可能写过类似
@@ -18,13 +18,13 @@ for (int i = 0; i < n; i ++)
但是,你想过 Python 在处理 for in 语句的时候,具体发生了什么吗?什么样的对象可以被 for in 来枚举呢?
# 容器迭代
## 容器迭代
容器这个概念非常好理解。
在 Python 中一切皆对象,对象的抽象就是类,而对象的集合就是容器。
列表list: [0, 1, 2],元组tuple: (0, 1, 2),字典dict: {0:0, 1:1, 2:2},集合set: set([0, 1, 2])都是容器。
列表`list: [0, 1, 2]`,元组`tuple: (0, 1, 2)`,字典`dict: {0:0, 1:1, 2:2}`,集合`set: set([0, 1, 2])`都是容器。
对于容器,你可以很直观地想象成多个元素在一起的单元;而不同容器的区别,正是在于内部数据结构的实现方法。
@@ -37,7 +37,7 @@ iterator = iter(iterable)
# do something
```
- 首先,在可迭代对象上调用内置 `iter` 函数以创建对应的<em>迭代器</em>
- 首先,在可迭代对象上调用内置 `iter` 函数以创建对应的*迭代器*
- 要获取序列中的下一个元素,在此迭代器上调用内置 `next` 函数。
如果没有下一个元素了,怎么办?
@@ -74,11 +74,11 @@ StopIteration
[1, 2, 3, 4]
```
# 英语练习,对迭代器的类比
## 英语练习,对迭代器的类比
<strong>Analogy</strong>: An iterable is like a book (one can flip through the pages) and an iterator for a book would be a bookmark (saves the position and can locate the next page). Calling `iter` on a book gives you a new bookmark independent of other bookmarks, but calling `iter` on a bookmark gives you the bookmark itself, without changing its position at all. Calling `next` on the bookmark moves it to the next page, but does not change the pages in the book. Calling `next` on the book wouldn't make sense semantically. We can also have multiple bookmarks, all independent of each other.
**Analogy**: An iterable is like a book (one can flip through the pages) and an iterator for a book would be a bookmark (saves the position and can locate the next page). Calling `iter` on a book gives you a new bookmark independent of other bookmarks, but calling `iter` on a bookmark gives you the bookmark itself, without changing its position at all. Calling `next` on the bookmark moves it to the next page, but does not change the pages in the book. Calling `next` on the book wouldn't make sense semantically. We can also have multiple bookmarks, all independent of each other.
# 生成器:懒人迭代器!
## 生成器:懒人迭代器!
```python
def test_iterator():
@@ -114,7 +114,8 @@ Wall time: 12.5 s
声明一个迭代器很简单,[i for i in range(100000000)]就可以生成一个包含一亿元素的列表。每个元素在生成后都会保存到内存中,你通过代码可以看到,它们占用了巨量的内存,内存不够的话就会出现 OOM 错误。
了解下 yield函数吧他可以返回一个生成器对象试试看懂这个
::: warning 🤔 了解下 yield函数吧他可以返回一个生成器对象试试看懂这个
:::
```python
>>> def gen_list(lst):
@@ -133,7 +134,7 @@ Wall time: 12.5 s
StopIteration
```
# 思考题python 会显示什么?为什么?
## 思考题python 会显示什么?为什么?
```python
>>> s = [1, 2, 3, 4]
@@ -185,9 +186,9 @@ ______
______
```
# 任务
## 任务
P10实现 `count`,它接受一个迭代器 `t` 并返回该值 `x` 出现在 的第一个 n 个元素中的次数 `t`
P10实现 `count`,它接受一个迭代器 `t` 并返回该值 `x` 出现在的前 n 个元素中的次数 `t`
```python
def count(t, n, x):

View File

@@ -1,6 +1,6 @@
# 结语
# 感觉学了不少内容,又感觉什么都没学?
## 感觉学了不少内容,又感觉什么都没学?
确实,这也是学习过程中一个非常普遍存在的状态,你学了五个非常重要的 python 语言的特性,但是在你用他们真正来优化代码解决代码之前,你都无法真正的掌握他们。
@@ -10,11 +10,11 @@
同时python 的核心特性就这些吗?远远不止呢,这些只是你入手其的敲门砖,我在下面会列举一些别的特性,你可以自行前去了解,也可以等到你真正遇到问题的时候去思考?
# 为什么没有突出面向对象
## 为什么没有突出面向对象
因为代码量实在是太少了,当你去理解面向对象的时候的伟大意义时,最好与 C 语言这种面向过程的语言进行对比,不过,如果你完成了我们的文字冒险小游戏的时候,你可能会有非常深刻的体验。
# 还有什么是我值得注意的?
## 还有什么是我值得注意的?
这些内容值得你去学习与思考,但是碍于各种因素,我暂时没有详细介绍
@@ -30,9 +30,9 @@
如果有机会,我会继续补充相关内容
值得一提的是:后面人工智能模块,我们将以 python 为主去进行编程,这对完成了所有任务的你一定是 a piece of cake!
值得一提的是后面人工智能模块,我们将以 python 为主去进行编程,这对完成了所有任务的你一定是 a piece of cake!
# 一些不错的补充
## 一些不错的补充
[WTF for python](https://github.com/robertparley/wtfpython-cn)

View File

@@ -1,6 +1,6 @@
# Python for fun
值得一提的是,Python 是面向对象的编程语言,与你之前书写的 C 语言(面向过程)有非常多的不同。
值得一提的是Python 是面向对象的编程语言,与你之前书写的 C 语言(面向过程)有非常多的不同。
我们为什么要选择要使用 Python 来首先讲解面向对象这个概念?

Some files were not shown because too many files have changed in this diff Show More