n皇后问题(英文)http://mathworld.wolfram.com/QueensProblem.html
很负责任的挖了一个:
这就是著名的八皇后问题。八个皇后在排列时不能同在一行、一列或一条斜
线上。在8!=40320种排列中共有92种解决方案。
“八皇后”动态图形的实现
八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动,使教学能产生良好的效果。下面是笔者用Turbo C实现的八皇后问题的图形程序,能够演示全部的92组解。八皇后问题动态图形的实现,主要应解决以下两个问题。
1.回溯算法的实现
(1)为解决这个问题,我们把棋盘的横坐标定为i,纵坐标定为j,i和j的取值范围是从1到8。当某个皇后占了位置(i,j)时,在这个位置的垂直方向、水平方向和斜线方向都不能再放其它皇后了。用语句实现,可定义如下三个整型数组:a[8],b[15],c[24]。其中:
a[j-1]=1 第j列上无皇后
a[j-1]=0 第j列上有皇后
b[i+j-2]=1 (i,j)的对角线(左上至右下)无皇后
b[i+j-2]=0 (i,j)的对角线(左上至右下)有皇后
c[i-j+7]=1 (i,j)的对角线(右上至左下)无皇后
c[i-j+7]=0 (i,j)的对角线(右上至左下)有皇后
(2)为第i个皇后选择位置的算法如下:
for(j=1j<=8j++) /*第i个皇后在第j行*/
if ((i,j)位置为空)) /*即相应的三个数组的对应元素值为1*/
{占用位置(i,j) /*置相应的三个数组对应的元素值为0*/
if i<8
为i+1个皇后选择合适的位置;
else 输出一个解
}
2.图形存取
在Turbo C语言中,图形的存取可用如下标准函数实现:
size=imagesize(x1,y1,x2,y2) 返回存储区域所需字节数。
arrow=malloc(size)建立指定大小的动态区域位图,并设定一指针arrow。
getimage(x1,y1,x2,y2,arrow)将指定区域位图存于一缓冲区。
putimage(x,y,arrow,copy)将位图置于屏幕上以(x,y)左上角的区域。
3. 程序清单如下
#i nclude <graphics.h>
#i nclude <stdlib.h>
#i nclude <stdio.h>
#i nclude <dos.h>
char n[3]={0,0}/*用于记录第几组解*/
int a[8],b[15],c[24],i
int h[8]={127,177,227,277,327,377,427,477}/*每个皇后的行坐标*/
int l[8]={252,217,182,147,112,77,42,7}/*每个皇后的列坐标*/
void *arrow
void try(int i)
{int j
for (j=1j<=8j++)
if (a[j-1]+b[i+j-2]+c[i-j+7]==3) /*如果第i列第j行为空*/
{a[j-1]=0b[i+j-2]=0c[i-j+7]=0/*占用第i列第j行*/
putimage(h[i-1],l[j-1],arrow,COPY_PUT)/*显示皇后图形*/
delay(500)/*延时*/
if(i<8) try(i+1)
else /*输出一组解*/
{n[1]++if (n[1]>9) {n[0]++n[1]=0}
bar(260,300,390,340)/*显示第n组解*/
outtextxy(275,300,n)
delay(3000)
}
a[j-1]=1b[i+j-2]=1c[i-j+7]=1
putimage(h[i-1],l[j-1],arrow,XOR_PUT)/*消去皇后,继续寻找下一组解*/
delay(500)
}
}
int main(void)
{int gdrive=DETECT,gmode,errorcode
unsigned int size
initgraph(&gdrive,&gmode,"")
errorcode=graphresult()
if (errorcode!=grOk)
{printf("Graphics error\n")exit(1)}
rectangle(50,5,100,40)
rectangle(60,25,90,33)
/*画皇冠*/
line(60,28,90,28)line(60,25,55,15)
line(55,15,68,25)line(68,25,68,10)
line(68,10,75,25)line(75,25,82,10)
line(82,10,82,25)line(82,25,95,15)
line(95,15,90,25)
size=imagesize(52,7,98,38)arrow=malloc(size)
getimage(52,7,98,38,arrow)/*把皇冠保存到缓冲区*/
clearviewport()
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4)
setusercharsize(3, 1, 1, 1)
setfillstyle(1,4)
for (i=0i<=7i++) a[i]=1
for (i=0i<=14i++) b[i]=1
for (i=0i<=23i++) c[i]=1
for (i=0i<=8i++) line(125,i*35+5,525,i*35+5)/*画棋盘*/
for (i=0i<=8i++) line(125+i*50,5,125+i*50,285)
try(1)/*调用递归函数*/
delay(3000)
closegraph()
free(arrow)
}
八皇后问题的串行算法
1 八皇后问题
所谓八皇后问题,是在8*8格的棋盘上,放置8个皇后。要求每行每列放一个皇后,而且每一条对角线和每一条反对角线上不能有多于1个皇后,也即对同时放置在棋盘的两个皇后(row1,column1)和(row2,column2),不允许(column1-column2)=(row1-row2)或者(column1+row1)=(column2+row2)的情况出现。
2 八皇后问题的串行递归算法
八皇后问题最简单的串行解法为如下的递归算法:
(2.1)深度递归函数:
go(int step,int column)
{int i,j,place
row[step]=column
if (step==8)
outputresult( )/*结束递归打印结果*/
else /*继续递归*/
{for(place=1place<=8place++)
{for(j=1j<=stepj++)
if(collision(j ,row[j],step+1,place))
/*判断是否有列冲突、对角线或反对角线*/
goto skip_this_place
go(step+1,place)
skip_this_place:
}
}
}/* go */
(2.2)主函数:
void main( )
{int place,j
for(place=1place<=8place++)
go(1,place)
}/* main */
八皇后问题的并行算法
该算法是将八皇后所有可能的解放在相应的棋盘上,主进程负责生成初始化的棋盘,并将该棋盘发送到某个空闲的子进程,由该子进程求出该棋盘上满足初始化条件的所有的解。这里,我们假定主进程只初始化棋盘的前两列,即在棋盘的前两列分别放上2个皇后,这样就可以产生8*8=64个棋盘。
1 主进程算法
主进程等待所有的子进程,每当一个子进程空闲的时侯,就向主进程发送一个Ready(就绪)信号。主进程收到子进程的Ready信号后,就向该子进程发送一个棋盘。当主进程生成了所有的棋盘后,等待所有的子进程完成它们的工作。然后向每个子进程发送一个Finished信号,打印出各个子进程找到的解的总和,并退出。子进程接收到Finished信号也退出。
2 子进程算法
每个子进程在收到主进程发送过来的棋盘后,对该棋盘进行检查。若不合法,则放弃该棋盘。子进程回到空闲状态,然后向主进程发送Ready信号,申请新的棋盘若合法,则调用move_to_right(board,rowi,colj)寻找在该棋盘上剩下的6个皇后可以摆放的所有位置,move_to_right(board,rowi,colj)是个递归过程, 验证是否能在colj列rowi行以后的位置是否能放一个皇后。
1)首先将more_queen设置成FALSE;
以LEAF,TRUE和FLASE区分以下三种情况:
A)LEAF:成功放置但是已到边缘,colj现在已经比列的最大值大1,回退两列,检查是否能将待检查皇后放在哪一行:如果能,把more_queen设成TRUE
B)TRUE:成功放置皇后,检查这一列是否能有放置皇后的其他方式,如有,把more_queen设成TRUE
C)FALSE:不能放置,回退一列再试,如果能把more_queen设成TRUE ,如果皇后已在最后一行,必须再检查上一列。
2)如果more_queens=TRUE,仍需再次调用move_to_right(),为新棋盘分配空间,用xfer()将现有棋盘拷贝到nextboard,并进行下列情况的处理:
TRUE:得到一个皇后的位置,增大列数再试;
FALSE:失败,如果more_queen为真, 取回棋盘,保存上次调用的棋盘。将列数减小,取走皇后,增加行数,再调用move_to_right();
LEAF:得到一种解法,solution增一,将解法写入log_file,由于已到边缘,列数回退1,检查是否放置一个皇后,如果能,新加一个皇后后,调用move_to_right;如果不能,检查more_queen如果more_queen为真,将棋盘恢复到上次调用时保存的棋盘,将待检查的皇后下移,调用move_to_right。
八皇后问题的高效解法-递归版
// Yifi 2003 have fun! : )
//8 Queen 递归算法
//如果有一个Q 为 chess[i]=j
//则不安全的地方是 k行 j位置,j+k-i位置,j-k+i位置
class Queen8{
static final int QueenMax = 8
static int oktimes = 0
static int chess[] = new int[QueenMax]//每一个Queen的放置位置
public static void main(String args[]){
for (int i=0i<QueenMaxi++)chess[i]=-1
placequeen(0)
System.out.println("\n\n\n八皇后共有"+oktimes+"个解法 made by yifi 2003")
}
public static void placequeen(int num){ //num 为现在要放置的行数
int i=0
boolean qsave[] = new boolean[QueenMax]
for(i<QueenMaxi++) qsave[i]=true
//下面先把安全位数组完成
i=0//i 是现在要检查的数组值
while (i<num){
qsave[chess[i]]=false
int k=num-i
if ( (chess[i]+k >= 0) &&(chess[i]+k <QueenMax) ) qsave[chess[i]+k]=false
if ( (chess[i]-k >= 0) &&(chess[i]-k <QueenMax) ) qsave[chess[i]-k]=false
i++
}
//下面历遍安全位
for(i=0i<QueenMaxi++){
if (qsave[i]==false)continue
if (num<QueenMax-1){
chess[num]=i
placequeen(num+1)
}
else{ //num is last one
chess[num]=i
oktimes++
System.out.println("这是第"+oktimes+"个解法 如下:")
System.out.println("第n行: 1 2 3 4 5 6 7 8")
for (i=0i<QueenMaxi++){
String row="第"+(i+1)+"行: "
if (chess[i]==0)
else
for(int j=0j<chess[i]j++) row+="--"
row+="++"
int j = chess[i]
while(j<QueenMax-1){row+="--"j++}
System.out.println(row)
}
}
}
//历遍完成就停止
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
char n[3]={\'0\',\'0\'}/*用于记录第几组解*/
int a[8],b[15],c[24],i
int h[8]={127,177,227,277,327,377,427,477}/*每个皇后的行坐标*/
int l[8]={252,217,182,147,112,77,42,7}/*每个皇后的列坐标*/
void *arrow
void try(int i)
{int j
for (j=1j<=8j++)
if (a[j-1]+b[i+j-2]+c[i-j+7]==3) /*如果第i列第j行为空*/
{a[j-1]=0b[i+j-2]=0c[i-j+7]=0/*占用第i列第j行*/
putimage(h[i-1],l[j-1],arrow,COPY_PUT)/*显示皇后图形*/
delay(500)/*延时*/
if(i<8) try(i+1)
else /*输出一组解*/
{n[1]++if (n[1]>\'9\') {n[0]++n[1]=\'0\'}
bar(260,300,390,340)/*显示第n组解*/
outtextxy(275,300,n)
delay(3000)
getch()
}
a[j-1]=1b[i+j-2]=1c[i-j+7]=1
putimage(h[i-1],l[j-1],arrow,XOR_PUT)/*消去皇后,继续寻找下一组解*/
delay(500)
}
}
int main(void)
{int gdrive=DETECT,gmode,errorcode
unsigned int size
initgraph(&gdrive,&gmode,"c:\\\\tc\\\\bgi")
errorcode=graphresult()
if (errorcode!=grOk)
{printf("Graphics error\\n")exit(1)}
rectangle(50,5,100,40)
rectangle(60,25,90,33)
/*画皇冠*/
line(60,28,90,28)line(60,25,55,15)
line(55,15,68,25)line(68,25,68,10)
line(68,10,75,25)line(75,25,82,10)
line(82,10,82,25)line(82,25,95,15)
line(95,15,90,25)
size=imagesize(52,7,98,38)arrow=malloc(size)
getimage(52,7,98,38,arrow)/*把皇冠保存到缓冲区*/
clearviewport()
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4)
setusercharsize(3, 1, 1, 1)
setfillstyle(1,4)
for (i=0i<=7i++) a[i]=1
for (i=0i<=14i++) b[i]=1
for (i=0i<=23i++) c[i]=1
for (i=0i<=8i++) line(125,i*35+5,525,i*35+5)/*画棋盘*/
for (i=0i<=8i++) line(125+i*50,5,125+i*50,285)
try(1)/*调用递归函数*/
delay(3000)
closegraph()
free(arrow)
}
这是改进般的挖来了:
这个...........楼上的诸位说的都是什么啊。今天刚好看到这个问题,把你的E-mail给我把,我有纯c的源码(RLC)。算了,直接贴关键部分吧。这个有一点C++成分,很容易改的。
bool CompressRunLength(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen, int nBitsPerSample, void* nRuns, int nRunCount, int nRunSize)
bool DecompressRunLength(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen)
#define GetDWORD(buf,bit,mask) ((*(DWORD*)(((BYTE*)buf)+((bit)>>3)))>>((bit)&7)&(mask))
#define GetWORD(buf,bit,mask) ((*(WORD*)(((BYTE*)buf)+((bit)>>3)))>>((bit)&7)&(mask))
int GetBitCount(int n)
{
int nBitCount = 0
while(n)
n >>= 1, nBitCount++
return nBitCount
}
int BinarySearch(void* pValue, int nVlaueSize, void* pArray, int nCount)
{
int nIndex, nResult, nStart = 0, nEnd = nCount-1
while(nStart <= nEnd)
{
nIndex = (nEnd+nStart)/2
if((nResult = memcmp((BYTE*)pArray+nIndex*nVlaueSize, pValue, nVlaueSize)) == 0)
return nIndex
if(nResult >0)
nEnd = nIndex-1
else
nStart = nIndex+1
}
return -1
}
bool CompressRunLength(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen, int nBitsPerSample, void* nRuns, int nRunCount, int nRunSize)
{
pDes = (BYTE*)malloc(nSrcLen*2)
memset(pDes, 0, nSrcLen*2)
nDesLen = sizeof(DWORD)
*(DWORD*)pDes = nSrcLen // save source length
*(pDes+nDesLen++) = nBitsPerSample// save bits per sample
*(pDes+nDesLen++) = nRunCount // save runs count
*(pDes+nDesLen++) = nRunSize // save run bytes
memcpy(pDes+nDesLen, nRuns, nRunCount*nRunSize)// save runs
nDesLen += nRunCount*nRunSize
nDesLen <<= 3// bytes to bits
if(nRunCount == 0)
nRunCount = 256, nRunSize = 1, nRuns = NULL
int nBitsPerTypeIndex = GetBitCount(nRunCount-1)
int nMaxRunLength = (1 <<nBitsPerSample)-1, nRunLength, nRunIndex, nByte = 0
// loop in the source buffer
while(nByte <nSrcLen)
if((nRuns &&(nRunIndex = BinarySearch(pSrc+nByte, nRunSize, nRuns, nRunCount)) != -1 &&
memcmp(pSrc+nByte+nRunSize, (BYTE*)nRuns+nRunIndex*nRunSize, nRunSize) == 0) ||
(!nRuns &&(nRunIndex = *(pSrc+nByte)) == *(pSrc+nByte+1)))
{ // set bit to 1 to indicate type found
*(pDes+(nDesLen>>3)) |= 1 <<(nDesLen&7)
*(DWORD*)(pDes+(++nDesLen>>3)) |= nRunIndex <<(nDesLen&7)
nDesLen += nBitsPerTypeIndex
// skip the two repeated runs
nByte += nRunSize*2
// get run length - 2 (without the two repeated runs)
nRunLength = 0
while(nRunLength <nMaxRunLength &&nByte <nSrcLen &&
((nRuns &&memcmp(pSrc+nByte, (BYTE*)nRuns+nRunIndex*nRunSize, nRunSize) == 0) || (!nRuns &&(BYTE)nRunIndex == *(pSrc+nByte))))
nRunLength++, nByte += nRunSize
// save run length and increment destination length by bits per sample
*(DWORD*)(pDes+(nDesLen>>3)) |= nRunLength <<(nDesLen&7)
nDesLen += nBitsPerSample
}
else // copy one byte
*(WORD*)(pDes+(++nDesLen>>3)) |= *(pSrc+nByte++) <<(nDesLen&7), nDesLen += 8
nDesLen = (nDesLen+7)/8// bits to bytes
pDes = (BYTE*)realloc(pDes, nDesLen)
return true
}
bool DecompressRunLength(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen)
{
if(nSrcLen == 0)
return true
// allocate destination buffer
nDesLen = *(DWORD*)pSrc
pDes = (BYTE*)malloc(nDesLen)
memset(pDes, 0, nDesLen)
// copy compression information
int nSrcIndex = sizeof(DWORD)
int nBitsPerSample = *(pSrc+nSrcIndex++)
int nRunCount = *(pSrc+nSrcIndex++)
int nRunSize = *(pSrc+nSrcIndex++)
void* nRuns = pSrc+nSrcIndex
nSrcIndex += nRunSize*nRunCount
nSrcIndex <<= 3// bytes to bits
if(nRunCount == 0)
nRunCount = 256, nRunSize = 1, nRuns = NULL
int nBitsPerTypeIndex = GetBitCount(nRunCount-1)
int nMaxTypeIndex = (1 <<nBitsPerTypeIndex)-1
int nMaxRunLength = (1 <<nBitsPerSample)-1
int nDesIndex = 0, nRunLength, nRunIndex, nRun, nByte
nSrcLen <<= 3// bytes to bits
while(nSrcIndex <nSrcLen-8)
if((*(pSrc+(nSrcIndex>>3)) >>(nSrcIndex++&7)) &1)
{
nRunIndex = GetDWORD(pSrc, nSrcIndex, nMaxTypeIndex), nSrcIndex += nBitsPerTypeIndex
nRunLength = GetDWORD(pSrc, nSrcIndex, nMaxRunLength)+2, nSrcIndex += nBitsPerSample
for(nRun = 0nRun <nRunLengthnRun++)
for(nByte = 0nByte <nRunSizenByte++, nDesIndex += 8)
*(WORD*)(pDes+(nDesIndex>>3)) |= nRuns ? GetWORD(nRuns+nRunSize*nRunIndex, nByte<<3, 0xff) : (BYTE)nRunIndex
}
else // copy one byte
*(WORD*)(pDes+(nDesIndex>>3)) |= GetWORD(pSrc, nSrcIndex, 0xff), nDesIndex += 8, nSrcIndex += 8
return true
}
有关图形窗口和图形屏幕 *** 作函数一、图形窗口 *** 作
象文本方式下可以设定屏幕窗口一样,图形方式下也可以在屏幕上某一区域设定窗口,只是设定的为图形窗口而已,其后的有关图形 *** 作都将以这个窗口的左上角 (0, 0)作为坐标原点,而且可为通过设置使窗口之外的区域为不可接触。这样,所有的图形 *** 作就被限定在窗口内进行。 void far setviewport(int xl,int yl,int x2, int y2,int clipflag)设定一个以(xl,yl)象元点为左上角,(x2,y2)象元为右下角的图
形窗口,其中x1,y1,x2,y2是相对于整个屏幕的坐标。若 clipflag为非0,则设定的图形以外部分不可接触,若clipflag为0,则图形窗口
以外可以接触。
void far clearviewport(void)清除现行图形窗口的内容。
void far getviewsettings(struct viewporttypefar * viewport)获得关于现行窗口的信息,并将其存于viewporttype定义的结构
变量viewport中,其中viewporttype的结构说明如下:
struct viewporttype
{
int left, top, right, bottom
int cliplag
}
注明:
1. 窗口颜色的设置与前面讲过的屏幕颜色设置相同,但屏幕背景色和窗口背景色只能是一种颜色,如果窗口背景色改变,整个屏幕的背景色也将改变这与文本窗口不同。
2. 可以在同一个屏幕上设置多个窗口,但只能有一个现行窗口工作,要对其它窗口 *** 作,通过将定义那个窗口的setviewport()函数再用一次即可。
3. 前面讲过图形屏幕 *** 作的函数均适合于对窗口的 *** 作。
二、屏幕 *** 作
除了清屏函数以外,关于屏幕 *** 作还有以下函数:
void far setactivepage(int pagenum)void far setvisualpage(int pagenum)这两个函数只用于EGA,VGA 以及HERCULES图形适配器。 setctivepage()函数是为图形输出选择激活页。所谓激活页是指后续图形的输出被写到函数选定的 pagenum页面,该页面并不一定可见。
setvisualpage()函数才使pagenum所指定的页面变成可见页。页面从0开始(Turbo C默认页)。如果先用setactivepage() 函数在不同页面
上画出一幅幅图像,再用setvisualpage() 函数交替显示,就可以实现一些动画的效果。
void far getimage(int xl,int yl, int x2,int y2,void far *mapbuf)void far putimge(int x,int,y,void * mapbuf, int op)unsined far imagesize(int xl,int yl,int x2,int y2)
这三个函数用于将屏幕上的图像复制到内存,然后再将内存中的图像送回到屏幕上。首先通过函数imagesize() 测试要保存左上角为
(xl,yl),右上角为(x2,y2)的图形屏幕区域内的全部内容需多少个字节,然后再给mapbuf分配一个所测数字节内存空间的指针。通过调用
getimage()函数就可将该区域内的图像保存在内存中,需要时可用putimage()函数将该图像输出到左上角为点(x, y)的位置上,其中
getimage()函数中的参数op规定如何释放内存中图像。 关于这个参数的定义参见下表:
putimage()函数中的op值
━━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含 义
——————————————————————————
COPY_PUT 0 复制
XOR_PUT 1 与屏幕图像异或的复制
OR_PUT 2 与屏幕图像或后复制
AND_PUT 3 与屏幕图像与后复制
NOT_PUT 4 复制反像的图形
━━━━━━━━━━━━━━━━━━━━━━━━━━
对于imagesize()函数,只能返回字节数小于64K字节的图像区域,否则将会出错,出错时返回-1。
本节介绍的函数在图像动画处理、菜单设计技巧中非常有用。
下面程序模拟两个小球动态碰撞过程。#include
#include
#include
int main()
{
int i, gdriver, gmode, size
void *buf
gdriver=DETECT
initgraph(&gdriver, &gmode, "c:\\caic\\bgi")
setbkcolor(BLUE)
cleardevice()
setcolor(LIGHTRED)
setlinestyle(0,0,1)
setfillstyle(1, 10)
circle(100, 200, 30)
floodfill(100, 200, 12)
size=imagesize(69, 169, 131, 231)
buf=malloc(size)
if(!buf) return -1
getimage(69, 169, 131, 231,buf)
putimage(500, 269, buf, COPY_PUT)
for(i=0i<185i++){
putimage(70+i, 170, buf, COPY_PUT)
putimage(500-i, 170, buf, COPY_PUT)
}
for(i=0i<185i++){
putimage(255-i, 170, buf, COPY_PUT)
putimage(315+i, 170, buf, COPY_PUT)
}
getch()
closegraph()
}
图形模式下的文本输出
在图形模式下,只能用标准输出函数,如printf(),puts(),putchar()函数输出文本到屏幕。除此之外,其它输出函数(如窗口输出函数)不能使用,即是可以输出的标准函数,也只以前景色为白色,按80列,25行的文本方式输出。
Turbo C2.0也提供了一些专门用于在图形显示模式下的文本输出函数。下面将分别进行介绍。
一、文本输出函数 void far outtext(char far *textstring)该函数输出字符串指针textstring所指的文本在现行位置。
void far outtextxy(int x, int y, char far *textstring)该函数输出字符串指针textstring所指的文本在规定的(x, y)位置。其中x和y为象元坐标。
说明:
这两个函数都是输出字符串,但经常会遇到输出数值或其它类型的数据,此时就必须使用格式化输出函数sprintf()。sprintf()函数的调用格式为: int sprintf(char *str, char *format, variable-list)它与printf()函数不同之处是将按格式化规定的内容写入str 指向的字符串中,返回值等于写入的字符个数。
例如:
'C110F1sprintf(s, "your TOEFL score is %d", mark)这里s应是字符串指针或数组,mark为整型变量。
二、有关文本字体、字型和输出方式的设置
有关图形方式下的文本输出函数,可以通过setcolor()函数设置输出文本的颜色。另外,也可以改变文本字体大小以及选择是水平方向输出还是垂直方向输出。
void far settexjustify(int horiz, int vert)该函数用于定位输出字符串。
对使用outtextxy(int x, int y, char far *str textstring)函数所输出的字符串,其中哪个点对应于定位坐标(x,y)在TurboC2.0中是有规定的。如果把一个字符串看成一个长方形的图形,在水平方向显示时,字符串长方形按垂直方向可分为顶部,中部和底部三个位置,水平方向可分为左,中,右三个位置,两者结合就有9个位置。
settextjustify()函数的第一个参数horiz 指出水平方向三个位置中的一个,第二个参数vert指出垂直方向三个位置中的一个,二者就确定了其中一个位置。当规定了这个位置后,用outtextxy () 函数输出字符串时,字符串长方形的这个规定位置就对准函数中的(x,y)位置。而对用outtext()函数输出字符串时,这个规定的位置就位于现行游标的位置。有关参数 horiz和vert的取值参见下表:
参数horiz和vert的取值
━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 用于
————————————————————————
LEFT_TEXT 0 水平
RIGHT_TEXT 2 水平
BOTTOM_TEXT 0 垂直
TOP_TEXT 2 垂直
CENTER_TEXT 1 水平或垂直
━━━━━━━━━━━━━━━━━━━━━━━━
void far settextstyle(int font, int direction,int charsize)
该函数用来设置输出字符的字形(由font确定)、输出方向(由direction确定)和字符大小(由charsize确定)等特性。
Turbo C2.0对函数中各个参数的规定见下列各表所示:
font的取值
━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义
————————————————————————
DEFAULT_FONT 0 8*8点阵字(缺省值)
TRIPLEX_FONT 1 三倍笔划字体
SMALL_FONT 2 小号笔划字体
SANSSERIF_FONT 3 无衬线笔划字体
GOTHIC_FONT 4 黑体笔划字
━━━━━━━━━━━━━━━━━━━━━━━━
direction的取值
━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义
————————————————————————
HORIZ_DIR 0 从左到右
VERT_DIR 1 从底到顶
━━━━━━━━━━━━━━━━━━━━━━━━
charsize的取值
━━━━━━━━━━━━━━━━━━━━━━━━
符号常数或数值 含义
————————————————————————
1 8*8点阵
2 16*16点阵
3 24*24点阵
4 32*32点阵
5 40*40点阵
6 48*48点阵
7 56*56点阵
8 64*64点阵
9 72*72点阵
10 80*80点阵
USER_CHAR_SIZE=0 用户定义的字符大小
━━━━━━━━━━━━━━━━━━━━━━━━
有关图形屏幕下文本输出和字体字型设置函数的用法请看下例:#include
#include
int main()
{
int i, gdriver, gmode
char s[30]
gdriver=DETECT
initgraph(&gdriver, &gmode, "c:\\caic\\bgi")
setbkcolor(BLUE)
cleardevice()
setviewport(100, 100, 540, 380, 1)
/*定义一个图形窗口*/
setfillstyle(1, 2)/*绿色以实填充*/
setcolor(YELLOW)
rectangle(0, 0, 439, 279)
floodfill(50, 50, 14)
setcolor(12)
settextstyle(1, 0, 8)
/*三重笔划字体, 水平放大8倍*/
outtextxy(20, 20, "Good Better")
setcolor(15)
settextstyle(3, 0, 5)
/*无衬笔划字体, 水平放大5倍*/
outtextxy(120, 120, "Good Better")
setcolor(14)
settextstyle(2, 0, 8)
i=620
sprintf(s, "Your score is %d", i)
/*将数字转化为字符串*/
outtextxy(30, 200, s)
/*指定位置输出字符串*/
setcolor(1)
settextstyle(4, 0, 3)
outtextxy(70, 240, s)
getch()
closegraph()
return 0
}
三、用户对文本字符大小的设置
前面介绍的settextstyle()函数,可以设定图形方式下输出文本字符这字体和大小但对于笔划型字体(除8*8点阵字以个的字体),只能在水平和垂直方向以相同的放大倍数放大。为此Turbo C2.0又提供了另外一个setusercharsize() 函数,对笔划字体可以分别设置水平和垂直方向的放大倍数。该函数的调用格式为:
void far setusercharsize(int mulx, int divx,int muly, int divy)该函数用来设置笔划型字和放大系数,它只有在settextstyle()
函数中的charsize为0(或USER_CHAR_SIZE)时才起作用,并且字体为函数settextstyle()规定的字体。调用函数 setusercharsize()后,每个显示在屏幕上的字符都以其缺省大小乘以mulx/divx为输出字符宽,乘以muly/divy为输出字符高。该函数的用法见下例:
#include
#include
int main()
{
int gdriver, gmode
gdriver=DETECT
initgraph(&gdriver, &gmode, "c:\\caic\\bgi")
setbkcolor(BLUE)
cleardevice()
setfillstyle(1, 2)/*设置填充方式*/
setcolor(WHITE)/*设置白色作图*/
rectangle(100, 100, 330, 380)
floodfill(50, 50, 14)/*填充方框以外的区域*/
setcolor(12)/*作图色为淡红*/
settextstyle(1, 0, 8)/*三重笔划字体,放大8倍*/
outtextxy(120, 120, "Very Good")
setusercharsize(2, 1, 4, 1)
/*水平放大2倍,垂直放大4倍*/
setcolor(15)
settextstyle(3, 0, 5)
/*无衬字笔划,放大5倍*/
outtextxy(220, 220, "Very Good")
setusercharsize(4, 1, 1, 1)
settextstyle(3, 0, 0)
outtextxy(180, 320, "Good")
getch()
closegraph()
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)