?? bankcodescan.java
字號:
package com.xnulw.pro7;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author slmcygh
* 吐血,中午11點多開始思考這個題目,到現在已經是晚上11:50了,頭暈腦脹的
* 現在代碼已經是很亂了,其實思路并不復雜,實現起來也不困難,可就是有些細節問題你很難發現,要經過大量的
* 調試,然后再慢慢的修改。我現在懷疑還有膽量再做
*
* 歡迎大家轉載,但請保留以上文字
* 同時歡迎大家訪問我的博客 http://xnulw.blogcn.com
*
*/
//條形碼元數據,即其中的某一位
class CodeData{
char[][] ch=new char[3][3];//記錄某一個數值的七段表示
int dataValue; //相應的數值
public CodeData(){
dataValue=0;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
ch[i][j]='.';
}
public CodeData(int value,String firstline,String secondline,String thirdline){
dataValue=value;
ch[0]=firstline.toCharArray();
ch[1]=secondline.toCharArray();
ch[2]=thirdline.toCharArray();
}
}
public class BankCodeScan {
private CodeData[] codeDictionary;//十種可能的元數據,可稱做字典
CodeData[] dataTmps=new CodeData[9];
private CodeData[] theCode=new CodeData[9];//某一個條形碼,是由9個元數據組成的
private int notEqualNum;//記錄條形碼中元數據不在字典中的個數,這里的值不會大于1,當大于1時即已經表明這個條形碼是不可識別的
private int notEqualInTheCode;//記錄不在字典中的元數據在條形碼的位置,只有當notEqualNum=1時才有含義,主要目標是為了后面的近似匹配
private BufferedReader inStream;
public BankCodeScan(){
try {
inStream=new BufferedReader(new FileReader("input.txt"));
} catch (FileNotFoundException e) {
// TODO 自動生成 catch 塊
e.printStackTrace();
}
}
//字典初始化
public void initDictionary(){
codeDictionary=new CodeData[10];
for(int i=0;i<10;i++){
codeDictionary[i]=new CodeData();
}
char[][] dat0={
{'.','_','.'},
{'|','.','|'},
{'|','_','|'}
};
char[][] dat1={
{'.','.','.'},
{'.','.','|'},
{'.','.','|'}
};
char[][] dat2={
{'.','_','.'},
{'.','_','|'},
{'|','_','.'}
};
char[][] dat3={
{'.','_','.'},
{'.','_','|'},
{'.','_','|'}
};
char[][] dat4={
{'.','.','.'},
{'|','_','|'},
{'.','.','|'}
};
char[][] dat5={
{'.','_','.'},
{'|','_','.'},
{'.','_','|'}
};
char[][] dat6={
{'.','_','.'},
{'|','_','.'},
{'|','_','|'}
};
char[][] dat7={
{'.','_','.'},
{'.','.','|'},
{'.','.','|'}
};
char[][] dat8={
{'.','_','.'},
{'|','_','|'},
{'|','_','|'}
};
char[][] dat9={
{'.','_','.'},
{'|','_','|'},
{'.','_','|'}
};
codeDictionary[0].ch=dat0;
codeDictionary[0].dataValue=0;
codeDictionary[1].ch=dat1;
codeDictionary[1].dataValue=1;
codeDictionary[2].ch=dat2;
codeDictionary[2].dataValue=2;
codeDictionary[3].ch=dat3;
codeDictionary[3].dataValue=3;
codeDictionary[4].ch=dat4;
codeDictionary[4].dataValue=4;
codeDictionary[5].ch=dat5;
codeDictionary[5].dataValue=5;
codeDictionary[6].ch=dat6;
codeDictionary[6].dataValue=6;
codeDictionary[7].ch=dat7;
codeDictionary[7].dataValue=7;
codeDictionary[8].ch=dat8;
codeDictionary[8].dataValue=8;
codeDictionary[9].ch=dat9;
codeDictionary[9].dataValue=9;
}
//這個方法主要是用于判斷當前元數據是否在字典中
public void equalJudge(CodeData[] theData,int theMetadataPosition){
int ntoEqualNumTag=0;//用于標識現在的元數據與字典中元數據都不相等的個數,如果等于10,則說明當前元數據不能在字典中找到
for(int num=0;num<10;num++){
int tag=ntoEqualNumTag;//tag主要用于判定當前元數據與字典中第num個元素是否相等
for(int i=-1;i<=1;i++) {
if(tag==(ntoEqualNumTag-1))break;//如果有小部分不相等,則其它部分沒必要比較,這個設計我覺得非常酷
for(int j=-1;j<=1;j++)
if(!((i==-1 && j==-1)||(i==-1 && j==1)))
if(theData[theMetadataPosition].ch[i+1][j+1]!=codeDictionary[num].ch[i+1][j+1]){
ntoEqualNumTag++;//不等標記加1,當值為10時,則說明字典中沒有與之相等的元素
break;
}
}
//比較一個元素,每小部分均相等,則整體相等
//下面是為條型碼中的第theMetadataPosition+1個數據賦值
if(tag==ntoEqualNumTag){
theData[theMetadataPosition].dataValue=codeDictionary[num].dataValue;
break;
}
}
if(ntoEqualNumTag==10){
notEqualNum++;//條形碼不在字典中的元數據加1
notEqualInTheCode=theMetadataPosition;//記錄最后一個不在字典中的無數據的位置
}
}
//這個方法是在確定了整個條形碼中只有一個元數據不確定時調用的匹配方法
//這里說的匹配不指相等,而是條形碼中的一個元數據指可以添加一些筆畫變成與字典中元素相等
public String isLikeJudge(CodeData[] theData,int notEqualInTheCode){
int notLikeTag=0;
int likeTag=0;//記錄可匹配的元數據個數
for(int num=0;num<10;num++){
int tag2=notLikeTag;//tag2主要用于判定當前元數據與字典中第num個元素是否可匹配
for(int i=-1;i<=1;i++){
if(tag2==(notLikeTag-1))break;//如果有小部分不匹配,則其它部分沒必要比較,這個設計我覺得非常酷
for(int j=-1;j<=1;j++)
if(!((i==-1 && j==-1)||(i==-1 && j==1)))
if(theData[notEqualInTheCode].ch[i+1][j+1]!=codeDictionary[num].ch[i+1][j+1]){
if(theData[notEqualInTheCode].ch[i+1][j+1]!='.'){
notLikeTag++;//不匹配加1
break;
}
}
}
//相等,則說明當前條形碼中的元數據是可以匹配的,但還不確定匹配后的結果是否滿足較驗條件
if(tag2==notLikeTag){
int temp=theData[notEqualInTheCode].dataValue;//保存數值,一旦匹配的結果不滿足較驗條件,便于恢復
theData[notEqualInTheCode].dataValue=codeDictionary[num].dataValue;//改變數據
if(validata())likeTag++;
else
theData[notEqualInTheCode].dataValue=temp;//恢復數據
}
}
if(likeTag==0)return "failur"; //不可匹配
if(likeTag==1)return display();//當前元數據只可匹配一個字典中的數據
if(likeTag>1)return"ambiguou";//當前元數據可匹配多個字典中的數據
return null;
}
//對識別出來的條形碼,讀取其值
private String display() {
String str="";
for(int i=0;i<9;i++){
str+=theCode[i].dataValue;
}
//這里很重要,主要是讓條形碼還原最初掃描進來的狀態
//因為,后面有可能多次對同一個條形碼進行操作,而這些操作要求條形碼具有最初的狀態
for(int i=0;i<9;i++){
this.theCode[i]=new CodeData(dataTmps[i].dataValue,new String(dataTmps[i].ch[0]),
new String(dataTmps[i].ch[1]),new String(dataTmps[i].ch[2]));
}
return str;
}
//條形碼掃描結果進行驗證
private boolean validata() {
int sum=0;
for(int i=1;i<10;i++){
int tmp=(10-i)*theCode[i-1].dataValue;
sum+=tmp;
}
if((sum%11)==0)return true;
return false;
}
//對某一條具體的條形碼進行處理
public void processACode(){
for(int i=0;i<9;i++){
//題目說過,掃描只可能最多出錯一個數據
if(notEqualNum>1){
System.out.println("failur");
break;
}
equalJudge(theCode, i);//檢查條形碼第(i+1)個數據是否在字典中
}
//這里就是當條形碼所有的數據都在字典中,即可識別時
//這里比較復雜,因為可識別的數據同樣是可以是某個數據因為掃描錯誤而得到,如7->1,8->0等
if(notEqualNum==0){
//1.這里不僅要考慮識別出的條形碼是否滿足較驗條件,
//2.同時又要考慮這些可識別的條形碼是否是別的條形碼因為掃描錯誤而得到
//最后結果只可能是3種情況,(1)都不滿足(2)有多個滿足(3)只有一個滿足
//結合1,2兩種情況,可以很容易的構建整個綜合結果的邏輯
String result="";//用于保存綜合兩種考慮的輸出結果
String s1="";//用于保存考慮1的輸出結果
if(this.validata()){
s1=display();
}else{
s1="failur";
}
int num=0;
String s2="failur";//用于保存考慮2的輸出結果
for(int i=0;i<9;i++){
// 這里因為,每一次元數據替代后就改變了原先條形碼,因此這里要保證的是每一次替代后,又還原為原先的條形碼
// 而這個操作,我們在display()方法中做了
String s2temp=this.isLikeJudge(theCode, i);
if("ambiguou".equals(s2temp)){
s2="ambiguou";
break;
}
else{
if(!"failur".equals(s2temp)){
if(!s2.equals(s2temp)){
s2=s2temp;
num++;
if(num>1){
s2="ambiguou";
break;
}
}
}
}
}
if("ambiguou".equals(s2)){
result=s2;
}else{
if("failur".equals(s2)){
if("failur".equals(s1)){
result="failur";
}else{
result=s1;
}
}else{
if("failur".equals(s1)){
result=s2;
}else{
if(s2.equals(s1)){
result=s2;
}else{
result="ambiguou";
}
}
}
}
System.out.println(result);
}
//有一個數據不可識別,notEqualInTheCode指明了該數據在條形碼中的位置是(notEqualInTheCode+1)
//匹配該數據
if(notEqualNum==1)System.out.println(isLikeJudge(theCode, notEqualInTheCode));
}
//驅動類,出于習慣把正常的操作步驟組織在這個方法里
public void driver() throws IOException{
String firstline;
String secondline;
String thirdline;
//循環讀取條形碼并進行處理
while((firstline=inStream.readLine())!=null){
if((secondline=inStream.readLine())!=null && (thirdline=inStream.readLine())!=null){
for(int i=0;i<9;i++){
theCode[i]=new CodeData(0,firstline.substring(i*3, (i+1)*3),
secondline.substring(i*3, (i+1)*3),
thirdline.substring(i*3, (i+1)*3));
}
//這里就是把條形碼的最初狀態作一個備份,以便需要的時候,還原其初始狀態
for(int i=0;i<9;i++){
dataTmps[i]=new CodeData(theCode[i].dataValue,new String(theCode[i].ch[0]),
new String(theCode[i].ch[1]),new String(theCode[i].ch[2]));
}
}
processACode();//處理這一條條形碼
this.notEqualNum=0;//恢復狀態,為處理下一條條形碼作準備
this.notEqualInTheCode=0;
}
}
public static void main(String[] args) throws IOException{
BankCodeScan bc=new BankCodeScan();
bc.initDictionary();
bc.driver();
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -